Как предотвратить пустые атрибуты xmlns в выводе из .NET XmlDocument? - PullRequest
111 голосов
/ 25 сентября 2008

При генерации XML из XmlDocument в .NET пустой атрибут xmlns появляется при первом добавлении элемента без связанного пространства имен; как это можно предотвратить?

Пример:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root",
    "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner"));
Console.WriteLine(xml.OuterXml);

Выход:

<root xmlns="whatever:name-space-1.0"><loner xmlns="" /></root>

Желаемый Выход:

<root xmlns="whatever:name-space-1.0"><loner /></root>

Есть ли решение, применимое к коду XmlDocument, а не то, что происходит после преобразования документа в строку с OuterXml?

Моя причина для этого состоит в том, чтобы посмотреть, могу ли я соответствовать стандартному XML конкретного протокола, используя сгенерированный XmlDocument XML. Пустой атрибут xmlns может не нарушать или не сбивать с толку синтаксический анализатор, но он также отсутствует в любом использовании, которое я видел для этого протокола.

Ответы [ 7 ]

103 голосов
/ 26 сентября 2008

Благодаря ответу Джереми Лью и немного больше игры, я понял, как удалить пустые атрибуты xmlns: передать пространство имен корневого узла при создании любого дочернего узла, который вы хотите, чтобы не префикс включен. Использование пространства имен без префикса в корне означает, что вам необходимо использовать это же пространство имен для дочерних элементов, чтобы они также не имели префиксов.

Фиксированный код:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root", "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner", "whatever:name-space-1.0")); 
Console.WriteLine(xml.OuterXml);

Спасибо всем за ваши ответы, которые привели меня в правильном направлении!

79 голосов
/ 30 декабря 2011

Это вариант ответа JeniT (спасибо большое, кстати!)

XmlElement new_element = doc.CreateElement("Foo", doc.DocumentElement.NamespaceURI);

Это избавляет от необходимости копировать или повторять пространство имен везде.

10 голосов
/ 25 сентября 2008

Если бы элемент <loner> в вашем примере XML не содержал декларацию пространства имен по умолчанию xmlns, он был бы в пространстве имен whatever:name-space-1.0, а не в пространстве имен. Если это то, что вы хотите, вам нужно создать элемент в этом пространстве имен:

xml.CreateElement("loner", "whatever:name-space-1.0")

Если вы хотите, чтобы элемент <loner> не находился в пространстве имен, то созданный XML-файл - это именно то, что вам нужно, и вам не стоит беспокоиться об атрибуте xmlns, который был автоматически добавлен для вас.

7 голосов
/ 25 сентября 2008

Поскольку root находится в пространстве без префиксов, любой дочерний элемент root, который хочет быть без пространства имен, должен быть выведен, как в вашем примере. Решением будет префикс корневого элемента следующим образом:

<w:root xmlns:w="whatever:name-space-1.0">
   <loner/>
</w:root>

код:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement( "w", "root", "whatever:name-space-1.0" );
doc.AppendChild( root );
root.AppendChild( doc.CreateElement( "loner" ) );
Console.WriteLine(doc.OuterXml);
0 голосов
/ 06 июня 2015

Да, вы можете запретить XMLNS из XmlElement. Первое время создания, оно наступает: вот так

<trkpt lat="30.53597" lon="-97.753324" xmlns="">
    <ele>249.118774</ele>
    <time>2006-05-05T14:34:44Z</time>
</trkpt>

Изменить код: и передать пространство имен xml как это

C # код:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
0 голосов
/ 23 февраля 2011

Я решил проблему с помощью фабричного шаблона. Я создал фабрику для объектов XElement. В качестве параметра для создания фабрики я указал объект XNamespace. Таким образом, каждый раз, когда XElement создается фабрикой, пространство имен будет добавляться автоматически. Вот код фабрики:

internal class XElementFactory
{
    private readonly XNamespace currentNs;

    public XElementFactory(XNamespace ns)
    {
        this.currentNs = ns;
    }

    internal XElement CreateXElement(String name, params object[] content)
    {
        return new XElement(currentNs + name, content);
    }
}
0 голосов
/ 25 сентября 2008

Если возможно, создайте класс сериализации, затем выполните:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);

Это безопаснее, и вы можете контролировать пространства имен с атрибутами, если вам действительно нужен больший контроль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...