Правильное управление пространством имен в .NET XmlWriter - PullRequest
15 голосов
/ 26 августа 2008

Я широко использую технологии .NET XML в своей работе. Одна из вещей, которые мне очень нравятся, это движок XSLT, точнее его расширяемость. Однако есть один маленький кусочек, который продолжает вызывать раздражение. Ничего особенного или чего-то, с чем мы не можем жить, но это мешает нам создавать прекрасный XML, который мы хотели бы создать.

Одна из вещей, которую мы делаем, - это преобразование узлов в линию и импорт узлов из одного XML-документа в другой.

К сожалению, когда вы сохраняете узлы в XmlTextWriter (фактически независимо от того, что возвращает XmlWriter.Create(Stream)), определения пространства имен добавляются туда независимо от того, необходимо это (ранее определено) или нет. Вы получаете вид следующего 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. В качестве дополнительного бонуса я хотел бы переопределить пространство имен по умолчанию, меняя его по мере написания узла.

Ответы [ 3 ]

14 голосов
/ 26 июня 2011

Используйте этот код:

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>
1 голос
/ 27 июня 2011

Вы пробовали это?

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'

1 голос
/ 21 июня 2011

Я не уверен, что это то, что вы ищете, но вы можете использовать этот вид кода, когда начинаете писать в поток XML:

myWriter.WriteAttributeString("xmlns", "abx", null, "http://bladibla");

XmlWriter должен запомнить его и больше не переписывать. Возможно, он не на 100% пуленепробиваемый, но работает большую часть времени.

...