XDocument,XPath和命名空间的奇怪之处

时间:2010-09-15 08:34:23

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

我有一个XML文档,如下所示:

<kmsg xmlns="http://url1" xmlns:env="url1" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://location that does not exist.xsd">
<header>
    <env:envelope>
        <env:source branch="907" machine="0" password="J123"/>
    </env:envelope>
</header>
<body>
    <OrderResponse xmlns="urn:schemasbasdaorg:2000:orderResponse:xdr:3.01">
        <SomeMoreNodes/>
    </OrderResponse>
</body>

尽管指定了命名空间,但它没有任何可用的模式(我从外部源获取这些,因此无法控制)。我正在使用XDocument解析它,但不会为不在env命名空间中的项获取空值。我正在设置这样的XDocument:

XDocument Source = XDocument.Load("Testfile.xml");

XmlNamespaceManager oManager = new XmlNamespaceManager(new NameTable());
oManager.AddNamespace(String.Empty, "http://xml.kerridge.net/k8msg");
oManager.AddNamespace("env", "http://xml.kerridge.net/k8msgEnvelope");

然后我尝试获取值:

?Source.XPathSelectElement(“// kmsg”,oManager)

?Source.XPathSelectElement(“// header”,oManager)

?Source.XPathSelectElement(“// env:source”,oManager)

正确获取节点

我认为这与我设置命名空间管理器错误有关,但我无法弄清楚如何修复它。任何帮助都会很棒。

由于

2 个答案:

答案 0 :(得分:19)

除了@Mads-Hansen的正确评论之外,您还有一个典型的问题,即没有为其中一个名称空间定义(非空)前缀。

记住:XPath认为任何未加前缀的名称都在“无名称空间”中。

因此这是错误的

Source.XPathSelectElement("//kmsg", oManager)

此XPath表达式要选择“无命名空间”中的所有kmsg元素,并且它正确选择任何内容,因为提供的XML文档中的任何kmsg元素都在"http://url1"中命名空间,而不是“无命名空间”。

要正确执行

oManager.AddNamespace("xxx", "http://url1");      
Source.XPathSelectElement("//xxx:kmsg", oManager)

答案 1 :(得分:1)

源XML中声明的namespace-URI与您在XmlNamespaceManager注册的namespace-URI不匹配。

在源XML中:

  1. 匿名命名空间(无前缀)具有namespace-uri:http://url1
  2. env 名称空间前缀具有namespace-uri:url1
  3. 在您声明的XmlNamespaceManager中:

    1. 匿名命名空间(无前缀)具有namespace-uri:http://xml.kerridge.net/k8msg
    2. env 名称空间前缀具有namespace-uri:http://xml.kerridge.net/k8msgEnvelope
    3. namespace-uri值必须匹配,否则你选择不同的元素名称,永远不会匹配。