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

C# 当XML具有名称空间时,如何使用XPath动态查询XDocument,c#,xml,xpath,C#,Xml,Xpath,我一直在使用XPath获取XDocument中的节点字符串。然后,XPath可以使用xdoc.XPathSelectElement(XPath)查询节点 但是,对于使用名称空间的XML文档,此操作失败,如下所示: <?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://s

我一直在使用
XPath
获取
XDocument
中的节点字符串。然后,XPath可以使用
xdoc.XPathSelectElement(XPath)
查询节点

但是,对于使用名称空间的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>
但是,使用XPathSelectElement和上述XPath查询XDocument会产生
null
,因为没有指定名称空间

根据我查阅的答案,解决办法是。但是,我的路径是动态生成的(我事先不知道XML文档的名称空间或结构),因此手动调整字符串不是一个选项

我的问题是:

  • 有没有一种方法可以完全忽略名称空间而使用XPath进行查询
。但是,如果多个节点的名称为LocalName(这通常出现在我正在解析的XML中),则这种方法会失败,因为按名称搜索只会完全抛弃XPath的特殊性


澄清一下:我事先不知道XML文档是什么样子,XPath和名称空间是在运行时确定的,而不是在编译时确定的。因此,手动添加仅适用于此特定示例的字符串通常不起作用。

下面的代码是xml linq,只适用于一个节点。对于多个节点,您必须添加额外的搜索信息以获得您要查找的确切节点

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;

        }
    }
}
​

下面的代码是xml linq,将与一个节点一起工作。对于多个节点,您必须添加额外的搜索信息以获得您要查找的确切节点

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;

        }
    }
}
​

谢谢,但这行不通,因为我事先不知道名称空间(甚至不知道XML是什么样子的)。您的响应没有任何意义。我正在动态查询未知的XML文档,因此XPath和命名空间只能在运行时知道,而不能在编译时知道。您可以使用变量替换任何硬编码字符串(双引号),以便在运行时它可以是动态的。谢谢,但这不起作用,因为我不知道命名空间(甚至是XML的外观)。要搜索XML,您需要知道您要查找的内容。您的响应没有任何意义。我正在动态查询未知的XML文档,因此XPath和命名空间只能在运行时知道,而不能在编译时知道。您可以替换任何硬编码字符串(双引号)使用变量,使运行时可以是动态的。