Правильное управление пространством имен в .NET XmlWriter
Я широко использую технологии .NET XML в своей работе. Одна из вещей, которые мне очень нравятся, это движок XSLT, точнее его расширяемость. Однако есть один маленький кусочек, который продолжает вызывать раздражение. Ничего особенного или чего-то, с чем мы не можем жить, но это мешает нам создавать прекрасный XML, который мы хотели бы создать.
Одна из вещей, которые мы делаем, - это преобразуем встроенные узлы и импортируем узлы из одного документа XML в другой.
К сожалению, когда вы сохраняете узлы в XmlTextWriter
(фактически независимо от того, что возвращает XmlWriter.Create(Stream)
), определения пространства имен XmlTextWriter
туда независимо от того, необходимо это (ранее определено) или нет. Вы получаете вид следующего XML:
<root xmlns:abx="http://bladibla">
<abx:child id="A">
<grandchild id="B">
<abx:grandgrandchild xmlns:abx="http://bladibla" />
</grandchild>
</abx:child>
</root>
У кого-нибудь есть предложение относительно того, как убедить .NET быть эффективным в отношении его определений пространства имен?
PS. В качестве дополнительного бонуса я хотел бы переопределить пространство имен по умолчанию, меняя его, когда я пишу узел.
Ответы
Ответ 1
Используйте этот код:
using (var writer = XmlWriter.Create("file.xml"))
{
const string Ns = "http://bladibla";
const string Prefix = "abx";
writer.WriteStartDocument();
writer.WriteStartElement("root");
// set root namespace
writer.WriteAttributeString("xmlns", Prefix, null, Ns);
writer.WriteStartElement(Prefix, "child", Ns);
writer.WriteAttributeString("id", "A");
writer.WriteStartElement("grandchild");
writer.WriteAttributeString("id", "B");
writer.WriteElementString(Prefix, "grandgrandchild", Ns, null);
// grandchild
writer.WriteEndElement();
// child
writer.WriteEndElement();
// root
writer.WriteEndElement();
writer.WriteEndDocument();
}
Этот код создавал желаемый результат:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:abx="http://bladibla">
<abx:child id="A">
<grandchild id="B">
<abx:grandgrandchild />
</grandchild>
</abx:child>
</root>
Ответ 2
Я не уверен, что это то, что вы ищете, но вы можете использовать этот код при начале записи в поток Xml:
myWriter.WriteAttributeString("xmlns", "abx", null, "http://bladibla");
XmlWriter должен помнить об этом, а не переписывать его больше. Он не может быть пуленепробиваемым на 100%, но он работает большую часть времени.
Ответ 3
Вы пробовали это?
Dim settings = New XmlWriterSettings With {.Indent = True,
.NamespaceHandling = NamespaceHandling.OmitDuplicates,
.OmitXmlDeclaration = True}
Dim s As New MemoryStream
Using writer = XmlWriter.Create(s, settings)
...
End Using
Интересно, что "NamespaceHandling.OmitDuplicates"
Ответ 4
Это сообщение может быть полезно. Также рассмотрите свойство Пространства имен классов XmlTextWriter\XmlTextReader.