Код выглядит так:
StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
s.Serialize(xmlWriter, objectToSerialize);
}
Результирующий сериализованный документ включает пространства имен, например:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
Чтобы удалить пространства имен xsi и xsd, я могу следовать ответу из раздела Как сериализовать объект в XML без получения xmlns = ”…”? ,
Я хочу, чтобы мой тег сообщения был <message>
(без каких-либо атрибутов пространства имен). Как я могу это сделать?
c#
.net
xml-serialization
NetSide
источник
источник
Ответы:
источник
s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Это второй из двух ответов.
Если вы хотите просто произвольно удалить все пространства имен из документа во время сериализации, вы можете сделать это, реализовав свой собственный XmlWriter.
Самый простой способ - унаследовать от XmlTextWriter и переопределить метод StartElement, который генерирует пространства имен. Метод StartElement вызывается XmlSerializer при отправке любых элементов, включая корневой. Переопределив пространство имен для каждого элемента и заменив его пустой строкой, вы удалили пространства имен из вывода.
Предположим, это тип:
Вот как вы могли бы использовать такую вещь во время сериализации:
Однако XmlTextWriter в некотором роде сломан. Согласно справочному документу , когда он пишет, он не проверяет следующее:
Эти проблемы с XmlTextWriter существуют с версии 1.1 .NET Framework, и они останутся для обратной совместимости. Если вас не беспокоят эти проблемы, непременно используйте XmlTextWriter. Но большинству людей хотелось бы немного большей надежности.
Чтобы получить это, все еще подавляя пространства имен во время сериализации, вместо того, чтобы быть производным от XmlTextWriter, определите конкретную реализацию абстрактного XmlWriter и его 24 методов.
Пример здесь:
Затем предоставьте производный класс, который переопределяет метод StartElement, как и раньше:
А затем используйте этот писатель так:
В этом заслуга Олега Ткаченко .
источник
LookupPrefix(string ns)
чтобы всегда возвращать пустую строку, чтобы удалить все объявления схемы.XmlWriter
иXmlWriterSettings
.Прочитав документацию Microsoft и несколько решений в Интернете, я нашел решение этой проблемы. Он работает как со встроенной, так
XmlSerializer
и с настраиваемой сериализацией XML черезIXmlSerialiazble
.А именно, я буду использовать тот же
MyTypeWithNamespaces
образец XML, который до сих пор использовался для ответов на этот вопрос.Это все для этого класса. Некоторые возражали против наличия
XmlSerializerNamespaces
объекта где-нибудь в их классах; но, как видите, я аккуратно спрятал его в конструкторе по умолчанию и предоставил общедоступное свойство для возврата пространств имен.Теперь, когда придет время сериализовать класс, вы должны использовать следующий код:
Как только вы это сделаете, вы должны получить следующий результат:
Я успешно использовал этот метод в недавнем проекте с глубокой иерархией классов, сериализованных в XML для вызовов веб-служб. В документации Microsoft не очень ясно, что делать с общедоступным
XmlSerializerNamespaces
участником после его создания, и многие думают, что это бесполезно. Но, следуя их документации и используя ее описанным выше способом, вы можете настроить, как XmlSerializer генерирует XML для ваших классов, не прибегая к неподдерживаемому поведению или «собственной» сериализации путем реализацииIXmlSerializable
.Я надеюсь, что этот ответ раз и навсегда положит конец тому, как избавиться от стандартных пространств
xsi
иxsd
пространств имен, сгенерированныхXmlSerializer
.ОБНОВЛЕНИЕ: я просто хочу убедиться, что ответил на вопрос OP об удалении всех пространств имен. Мой код выше подойдет для этого; позвольте мне показать вам, как это сделать. Теперь, в приведенном выше примере, вы действительно не можете избавиться от всех пространств имен (потому что используются два пространства имен). Где-то в вашем XML-документе вам понадобится что-то вроде
xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo
. Если класс в примере является частью более крупного документа, то где-то выше должно быть объявлено пространство имен для одного из (или обоих)Abracadbra
иWhoohoo
. Если нет, то элемент в одном или обоих пространствах имен должен быть украшен каким-либо префиксом (у вас не может быть двух пространств имен по умолчанию, верно?). Итак, в этом примереAbracadabra
это пространство имен defalt. Я мог бы внутри своегоMyTypeWithNamespaces
класса добавить префикс пространства имен дляWhoohoo
пространства имен следующим образом:Теперь в определении моего класса я указал, что
<Label/>
элемент находится в пространстве имен"urn:Whoohoo"
, поэтому мне больше ничего не нужно делать. Когда я сериализую класс, используя приведенный выше код сериализации без изменений, вот результат:Поскольку он
<Label>
находится в пространстве имен, отличном от остального документа, он должен каким-то образом быть «украшен» пространством имен. Обратите внимание , что до сих пор нетxsi
иxsd
пространств имен.источник
XmlWriter
то, что содержится в,XmlMediaTypeFormatter
что заставляет пространства имен xsi и xsd в моем выводе независимо. Это влияет только на тех, кто использует WebApi по умолчаниюXmlMediaTypeFormatter
. Я скопировал для него исходный код и изменил его, чтобы передать свое свойство Namespaces методу Serialize, так как это необходимо для предотвращенияXmlWriter
автоматического добавления двух значений по умолчанию. Смотрите этот ответXmlSerializerNamespaces
украшенныйXmlNamespacesDeclarationAttribute
. Это было взято непосредственно из MSDN и, по сути, использует эти объявленные пространства имен вместо пространств по умолчанию, предоставляемыхXmlSerializer
.Это первый из двух моих ответов на вопрос.
Если вам нужен точный контроль над пространствами имен - например, если вы хотите опустить некоторые из них, но не другие, или если вы хотите заменить одно пространство имен другим, вы можете сделать это с помощью XmlAttributeOverrides .
Предположим, у вас есть такое определение типа:
И этот псевдокод сериализации:
Вы получите что-то вроде этого XML:
Обратите внимание, что для корневого элемента есть пространство имен по умолчанию, а также отдельное пространство имен для элемента «Label». Эти пространства имен были продиктованы атрибутами, украшающими тип, в приведенном выше коде.
Платформа сериализации Xml в .NET включает возможность явно переопределить атрибуты, украшающие фактический код. Вы делаете это с помощью класса XmlAttributesOverrides и друзей. Предположим, у меня такой же тип, и я сериализую его следующим образом:
Результат выглядит так:
Вы удалили пространства имен.
Возникает логичный вопрос: можно ли удалить все пространства имен из произвольных типов во время сериализации, не выполняя явных переопределений? Ответ - ДА, и как это сделать - в моем следующем ответе.
источник
источник