如何在XmlDocument c#中处理XML中的命名空间

时间:2011-09-28 17:55:58

标签: c# xml

我有几个XML文档,所有这些文档都具有相同的结构(元素名称,属性名称和层次结构)。

但是,某些元素和属性在每个XML文档中都有自定义命名空间,这些命名空间在设计时是未知的。他们改变了,不要问......

如何在使用一组XPath遍历文档时处理此问题?

我应该在处理之前删除所有名称空间吗?

我可以使用XmlNamespaceManager自动注册所有名称空间吗?

有什么想法吗?

更新:一些示例(为清晰起见,省略了名称空间声明):

<root>
    <child attr="val" />
</root>

<root>
    <x:child attr="val" />
</root>

<root>
    <y:child z:attr="val" />
</root>

由于

5 个答案:

答案 0 :(得分:2)

假设你有以下xml:

  <root xmlns="first">
   <el1 xmlns="second">
    <el2 xmlns="third">...

您可以通过以下方式编写查询以忽略名称空间: /*[local-name()='root']/*[local-name()='el1']/*[local-name()='el2'] 等等 当然,您可以遍历整个文档以获取命名空间并将其加载到nsmanager中。但在一般情况下,这将导致您评估文档中的每个节点。在这种情况下,将文档视为对象树并且不使用XPath会更快。

答案 1 :(得分:1)

我相信你会在这个Stackoverflow线程中找到一些很好的见解

XPath + Namespace Driving me crazy

在我看来,你有两种解决方案之一:

1-如果事先了解了所有可能的命名空间的集合,那么在开始解析之前,您可以在XmlNamespaceManager中将它们全部注册

2-使用Xpath命名空间无关的选择器

当然,您总是可以从任何内联命名空间中清除xml文档,并在没有命名空间的干净的uniorm xml上开始解析..但老实说,我没有看到添加此开销步骤的好处。

答案 2 :(得分:0)

Scott Hanselman有一个nice article关于提取XML文档中的所有XML命名空间。据推测,当您获得所有XML命名空间时,您可以迭代所有这些命名空间并在命名空间管理器中注册它们。

答案 3 :(得分:0)

您可以尝试使用这样的方法去除名称空间:

//Implemented based on interface, not part of algorithm
public string RemoveAllNamespaces(string xmlDocument)
{
    return RemoveAllNamespaces(XElement.Parse(xmlDocument)).ToString();    
}

//Core recursion function
private XElement RemoveAllNamespaces(XElement xmlDocument)
{
    if (!xmlDocument.HasElements)
    {
        XElement xElement = new XElement(xmlDocument.Name.LocalName);
        xElement.Value = xmlDocument.Value;
        return xElement;
    }
    return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
}

有关详细信息,请参阅Peter Stegnar的回答:
How to remove all namespaces from XML with C#?

答案 4 :(得分:0)

您还可以使用带有通配符的直接节点测试,它将匹配任何命名空间(或缺少命名空间):

$your-document/*:root/*:child/@*:attr