C# 如何在XMLC文档中处理XML中的名称空间#

C# 如何在XMLC文档中处理XML中的名称空间#,c#,xml,C#,Xml,我有几个XML文档,它们都具有相同的结构(元素名、属性名和层次结构) 但是,有些元素和属性在每个XML文档中都有自定义名称空间,而这些名称空间在设计时是未知的。他们变了,不要问 当使用一组XPath遍历文档时,如何处理这个问题 我应该在处理之前删除所有名称空间吗 我可以自动向XmlNamespaceManager注册所有名称空间吗 有什么想法吗 更新:一些示例(为了清晰起见省略了名称空间声明): 谢谢我相信您会在这个Stackoverflow线程中找到一些很好的见解 我认为您有两种解决方案

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

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

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

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

我可以自动向XmlNamespaceManager注册所有名称空间吗

有什么想法吗

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



谢谢

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

我认为您有两种解决方案:

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

2-使用Xpath命名空间不可知选择器


当然,您始终可以从任何内联名称空间中删除xml文档,并在没有名称空间的干净的非格式xml上开始解析。。但老实说,我看不出增加这一开销步骤有什么好处。

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

我认为您有两种解决方案:

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

2-使用Xpath命名空间不可知选择器


当然,您始终可以从任何内联名称空间中删除xml文档,并在没有名称空间的干净的非格式xml上开始解析。。但老实说,我看不出增加这一开销步骤有什么好处。

假设您有以下xml:

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

...
您可以通过以下方式编写忽略名称空间的查询:
/*[local-name()='root']/*[local-name()='el1']/*[local-name()='el2']

当然,您可以迭代整个文档以获得名称空间并将其加载到nsmanager中。但在一般情况下,这将导致您计算文档中的每个节点。在这种情况下,只将文档视为对象树而不使用XPath会更快

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

...
您可以通过以下方式编写忽略名称空间的查询:
/*[local-name()='root']/*[local-name()='el1']/*[local-name()='el2']

当然,您可以迭代整个文档以获得名称空间并将其加载到nsmanager中。但在一般情况下,这将导致您计算文档中的每个节点。在这种情况下,只将文档视为对象树而不使用XPath会更快。

Scott Hanselman有一个关于提取XML文档中所有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的回答:

您可以尝试以下方法来剥离名称空间:

//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的回答:

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


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


名称空间还是前缀?如果使用前缀(无需执行任何操作),如果使用名称空间(使用XmlNamespaceManager注册),则没有任何好处,因为您将无法在不知道名称的情况下提前创建XPath。关于使用本地名称的答案可能是最好的方法。名称空间还是前缀?如果使用前缀(无需执行任何操作),如果使用名称空间(使用XmlNamespaceManager注册),则没有任何好处,因为您将无法在不知道名称的情况下提前创建XPath。关于使用本地名称的答案可能是最好的方法。这看起来像答案,特别是在命名空间前缀不同的情况下。这看起来像答案,特别是在命名空间前缀不同的情况下