简体   繁体   English

当XML具有名称空间时,如何使用XPath动态查询XDocument

[英]How to dynamically query XDocument using XPath when XML has namespaces

I've been using this absolute XPath extension to get XPath strings of nodes inside XDocument 's. 我一直在使用此绝对XPath扩展来获取XDocument内节点的XPath字符串。 The node can then later be queried by XPath using xdoc.XPathSelectElement(xpath) . 然后,XPath可以使用xdoc.XPathSelectElement(xpath)查询该节点。

However, this fails for XML documents that use namespaces, like the following: 但是,这对于使用名称空间的XML文档失败,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.svsxml.svs.com" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Header>
        <wsse:Security soapenv:mustUnderstand="1">
            <wsse:UsernameToken>
                <wsse:Username>Pizza</wsse:Username>
                <wsse:Password>Pie</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
</soapenv:Envelope>

Calling GetAbsoluteXPath on the Username node gives: 在“ Username节点上调用GetAbsoluteXPath可得到:

/Envelope/Header[1]/Security[1]/UsernameToken[1]/Username[1]

However, querying the XDocument with XPathSelectElement and the above XPath yields null , because no namespace is specified. 但是,使用XPathSelectElement和上面的XPath查询XDocument会产生null ,因为未指定名称空间。

According to answers I looked up, the solution is to add a NamespaceManager and manually edit the path . 根据我查找的答案,解决方案是添加NamespaceManager并手动编辑path However, my paths are dynamically-generated (I don't know the namespace or structure of the XML document in advance), so hand-tweaking the strings is not an option. 但是,我的路径是动态生成的(我事先不知道XML文档的名称空间或结构),因此手动调整字符串不是一种选择。

My question is: 我的问题是:

  • Is there a way to query using an XPath in a way which totally ignores namespaces? 有没有一种可以完全忽略名称空间的方式使用XPath进行查询的方法?

An answer to a similarly-named question was to query by local name instead of XPath . 一个类似问题的答案是使用本地名称而不是XPath进行查询 However, this fails when multiple nodes have the name LocalName (which often occurs in the XML I'm parsing), since searching by name only throws away the specificity of the XPath entirely. 但是,当多个节点使用名称LocalName(通常在我解析的XML中出现)时,此操作将失败,因为按名称搜索只会完全放弃XPath的特殊性。

For clarification : I don't know what the XML document looks like in advance, and the XPath and namespaces are determined at run-time, not compile-time. 为了澄清 :我不知道XML文档是什么样子,XPath和名称空间是在运行时而不是编译时确定的。 So manually adding strings that only work for this particular example won't work in general. 因此,手动添加仅适用于该特定示例的字符串通常不会起作用。

The code below is xml linq and will work with one node. 下面的代码是xml linq,将在一个节点上工作。 With multiple nodes you have to add addional search info to get the exact node(s) you are looking for. 对于多个节点,您必须添加其他搜索信息以获取您要查找的确切节点。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement envelope = (XElement)doc.FirstNode;
            XNamespace wsse =  envelope.GetNamespaceOfPrefix("wsse");
            string username = envelope.Descendants(wsse + "Username").FirstOrDefault().Value;

        }
    }
}
​

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM