如何在xmldocumentc#中处理XML中的名称空间

本文关键字:空间 XML 处理 xmldocumentc# | 更新日期: 2023-09-27 18:09:53

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

然而,有些元素和属性在每个XML文档中都有自定义的名称空间,这些名称空间在设计时是不知道的。他们会改变,不要问…

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

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

我可以自动向XmlNamespaceManager注册所有的命名空间吗?

任何想法吗?

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

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

谢谢

如何在xmldocumentc#中处理XML中的名称空间

假设您有以下xml:

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

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

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

XPath + Namespace让我抓狂

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

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

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

当然,您总是可以从任何内联名称空间中清除xml文档,并在没有名称空间的干净统一的xml上开始解析。但是老实说,我不认为增加这个额外的步骤有什么好处。

Scott Hanselman有一篇关于从XML文档中提取所有XML名称空间的好文章。假设,当您获得所有XML名称空间时,您可以遍历它们并在名称空间管理器中注册它们。

您可以尝试这样剥离名称空间:

//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的回答:
如何用c#从XML中删除所有名称空间?

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

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