Установка только одного пространства имен в LINQ - PullRequest
4 голосов
/ 10 ноября 2010

У меня проблемы с пространствами имен в LINQ. Итак, исходя из MSDN Tutorial , мы можем сделать следующее, чтобы добавить пространства имен в документ XML с помощью LINQ:

// Create an XML tree in a namespace.
XNamespace aw = "http://www.adventure-works.com";
XElement root = new XElement(aw + "Root",
    new XElement(aw + "Child", "child content")
);
Console.WriteLine(root);

Что даст вам XML:

<Root xmlns="http://www.adventure-works.com">
  <Child>child content</Child>
</Root>

Но то, что я хочу сделать, это:

XNamespace aw = "http://www.adventure-works.com";
XElement root = new XElement(aw + "Roots");
XElement child = new XElement("Child", "child content");
root.Add(child);

Console.WriteLine(root);

Но это дает мне следующий xml:

<Root xmlns="http://www.adventure-works.com">
    <Child xmlns="">child content</Child>
</Root>

Проблема в том, что я не хочу xmlns="" в моих дочерних элементах (РЕДАКТИРОВАТЬ: я не хочу никаких пространств имен в моих дочерних элементах) , я хочу, чтобы он выглядел так же, как первый способ производит это. Я создаю довольно большой файл XML, поэтому не могу добавить все элементы в одном объявлении, и мне нужно иметь возможность использовать методы Add и SetAttributeValue для нескольких XElements, все еще имеющих xmlns на первый элемент. Есть идеи, как мне это сделать?

Спасибо!

Ответы [ 2 ]

6 голосов
/ 10 ноября 2010

Это поведение является фундаментальным для набора информации XML. Эффект объявления xmlns распространяется на весь дочерний контент; поскольку вы не указали пространство имен для дочернего элемента, стандартное поведение - поместить его в безымянное пространство имен. Чтобы вложить элемент в безымянное пространство имен внутри того, который объявляет пространство имен по умолчанию, объявление xmlns='' требуется для сброса пространства имен по умолчанию на безымянное.

Подводя итог, на основе вашего редактирования:

  • Если вам не нужны пространства имен в ваших дочерних элементах, то явное xmlns='' требуется согласно спецификации XML Namespaces , чтобы переопределить пространство имен, объявленное в элементе документа.
  • Если вам не нужны объявления пространства имен ( т.е. xmlns='' stuff) в ваших дочерних элементах, вы должны убедиться, что такое же пространство имен добавлено в имена всех из них в коде.

Я не знаю, как заставить XElement автоматически наследовать пространство имен своего родителя. После того, как вы закончите сборку DOM, вы всегда можете постобработать его, чтобы везде установить одно пространство имен с чем-то похожим на это:

foreach(var element in doc.Descendants())
    element.Name = aw + element.Name.LocalName;

Я не верю, что делать это рекомендуется для чего-то другого, кроме одноразового кода, так как он, вероятно, будет иметь неблагоприятные последствия для удобства сопровождения. Ряд XML-документов, с которыми мне приходилось иметь дело со смешанными пространствами имен, и «разрушение» пространств имен, как это делает приведенный выше фрагмент кода, могут привести к срыву семантики документа со смешанным пространством имен.

0 голосов
/ 10 ноября 2010

Единственный способ, которым я могу придумать, - это собрать весь документ в коде, а затем написать метод общего назначения, чтобы применить одно пространство имен ко всем элементам. Это может быть неудобно, чтобы получить право, но, конечно, возможно .

В основном new XElement("Child") задокументировано для создания элемента без пространства имен - вы не сможете изменить это.

Другой вариант - извлечь все имена ваших элементов в переменные (возможно, локальные или статические только для чтения) и применить пространство имен там :

private static readonly XNamespace AdventureWorksNs = "http://www....";
private static readonly XName RootName = AdventureWorksNs + "Root";
private static readonly XName ChildName = AdventureWorksNs + "Child";

тогда

XElement root = new XElement(RootName,
    new XElement(ChildName, "child content")
);
...