在LINQ中仅设置一个命名空间

时间:2010-11-10 07:15:58

标签: c# linq namespaces linq-to-xml

我在LINQ中遇到了一些名称空间问题。因此,从MSDN's Tutorial开始,我们可以执行以下操作,使用LINQ将命名空间添加到XML文档:

// 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的{​​{1}}和SetAttributeValue方法第一个元素上的XElements。我有什么想法可以做到这一点吗?

谢谢!

2 个答案:

答案 0 :(得分:6)

此行为是XML信息集的基础。 xmlns声明的效果限定在所有子内容中;由于您没有为子元素指定命名空间,因此标准行为是将其放在未命名的命名空间中。为了将一个元素嵌套在一个声明默认命名空间的未命名命名空间内,需要xmlns=''声明将默认命名空间重置为未命名。

总结一下,根据你的编辑:

  • 如果您的子元素中不需要任何命名空间,则XML Namespaces specification需要显式xmlns='' 才能覆盖文档元素中声明的名称空间。
  • 如果您的子元素中不需要任何名称空间声明 xmlns=''内容),则需要确保相同名称空间被添加到代码中的所有名称

我无法让XElement自动继承其父级的命名空间。但是,在完成构建DOM之后,您可以随时对其进行后处理,以便在任何地方设置一个名称空间,类似于:

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

我不相信这样做除了一次性代码之外的其他任何东西都是可取的,因为它可能会对可维护性产生不利影响。我必须处理混合命名空间的许多XML文档,以及像上面的代码片段一样“粉碎”命名空间确实会破坏混合命名空间文档的语义。

答案 1 :(得分:0)

我能想到的唯一方法是在代码中构建整个文档,然后编写一个通用方法,将一个命名空间应用于所有元素。这可能很难做到正确,但肯定可能

基本上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")
);