当XML文档包含名称空间时,选择带有XPath的节点

时间:2016-12-15 06:48:08

标签: c# xml xpath xml-namespaces

我想使用XPath选择XML文档的节点。但是当XML文档包含xml-namespaces时它不起作用。 如何在考虑名称空间的情况下使用XPath搜索节点?

这是我的XML文档(简化):

<ComponentSettings xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Company.Product.Components.Model">
  <Created xmlns="http://schemas.datacontract.org/2004/07/Company.Configuration">2016-12-14T10:29:28.5614696+01:00</Created>
  <LastLoaded i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/Company.Configuration" />
  <LastSaved xmlns="http://schemas.datacontract.org/2004/07/Company.Configuration">2016-12-14T16:31:37.876987+01:00</LastSaved>
  <RemoteTracer>
    <TraceListener>
      <Key>f987d7bb-9dea-49b4-a689-88c4452d98e3</Key>
      <Url>http://192.168.56.1:9343/</Url>
    </TraceListener>
  </RemoteTracer>
</ComponentSettings>

我想获取RemoteTracer标记的TraceListener标记的所有Url标记。 这就是我得到它们的方法,但这只有在XML文档不使用命名空间时才有效:

componentConfigXmlDocument = new XmlDocument();
componentConfigXmlDocument.LoadXml(myXmlDocumentCode);
var remoteTracers = componentConfigXmlDocument.SelectNodes("//RemoteTracer/TraceListener/Url");

目前,我的解决方法是在加载XML之前使用正则表达式从XML原始字符串中删除所有名称空间。然后我的SelectNodes()工作正常。但这不是正确的解决方案。

1 个答案:

答案 0 :(得分:1)

这里有两个名称空间。首先是

http://schemas.datacontract.org/2004/07/Company.Product.Components.Model

根元素(ComponentSettings),RemoteTracer及其下面的所有内容都属于此命名空间。第二个命名空间是

http://schemas.datacontract.org/2004/07/Company.Configuration

CreatedLastLoadedSaved属于它。

要获取所需的节点,必须在xpath查询中为所有元素添加前缀,并使用各自的名称空间前缀。将这些前缀映射到实际的命名空间,您可以这样做:

var componentConfigXmlDocument = new XmlDocument();            
componentConfigXmlDocument.LoadXml(File.ReadAllText(@"G:\tmp\xml.txt"));
var ns = new XmlNamespaceManager(componentConfigXmlDocument.NameTable);
ns.AddNamespace("model", "http://schemas.datacontract.org/2004/07/Company.Product.Components.Model");
ns.AddNamespace("config", "http://schemas.datacontract.org/2004/07/Company.Configuration");

然后像这样查询:

var remoteTracers = componentConfigXmlDocument.SelectNodes("//model:RemoteTracer/model:TraceListener/model:Url", ns);