Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;名称空间';x';“未定义”;尽管先调用GetNamespacesScope_C#_.net_Xml_Xpath - Fatal编程技术网

C# &引用;名称空间';x';“未定义”;尽管先调用GetNamespacesScope

C# &引用;名称空间';x';“未定义”;尽管先调用GetNamespacesScope,c#,.net,xml,xpath,C#,.net,Xml,Xpath,我正在尝试使用xPathNavigator解析c#.NET中的有效XML文档。XML文档的开头如下所示: <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv

我正在尝试使用
xPathNavigator
解析c#.NET中的有效XML文档。XML文档的开头如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:myResponse xmlns:ns1="ExampleNS" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <myReturn href="#2" />
我要做的是将XML文档作为字符串,将其加载到
XmlDocument
对象中。然后我创建一个导航器,移动到根元素并调用
GetNamespacesInScope(XmlNamespaceScope.All)
。我循环遍历这个集合,其中包含根目录上定义的
xml
soapenv
xsd
xsi
的名称空间,并将它们添加到名称空间管理器中。然后我创建一个
xPathNavigator
并调用
Evaluate
,然后获取异常

代码如下:

string response = GetXMLString();
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(response);

var xmlDocumentNavigator = xmlDocument.CreateNavigator();
xmlDocumentNavigator.MoveToFollowing(XPathNodeType.Element);
var xnm = new XmlNamespaceManager(xmlDocument.NameTable);
var namespacesInScope = xmlDocumentNavigator.GetNamespacesInScope(XmlNamespaceScope.All);
if (namespacesInScope != null)
{
    foreach (var prefix in namespacesInScope.Keys)
    {
        xnm.AddNamespace(prefix, namespacesInScope[prefix]);
    }
}

var xPathDocument = new XPathDocument(new StringReader(response));
var xPathNavigator = xPathDocument.CreateNavigator();

xPathNavigator.Evaluate("/soapenv:Envelope/soapenv:Body/ns1:myResponse/myReturn", xnm);

为什么
GetNamespacesInScope
方法不在
ns1
上使用?

问题是
GetNamespacesInScope
只返回导航器当前节点范围内的名称空间(我猜该方法建议:)

获取所有名称空间的一种方法是遍历所有元素,获取名称空间,然后重新组装唯一的元素

字典合并代码


问题是
GetNamespacesInScope
只返回导航器当前节点范围内的名称空间(正如我猜想的方法所建议的:)

获取所有名称空间的一种方法是遍历所有元素,获取名称空间,然后重新组装唯一的元素

字典合并代码


只添加您事先知道需要执行XPath查询的名称空间怎么样

你可以直接写

xnm.AddNamespace("MyNS", "ExampleNS");
然后

xPathNavigator
    .Evaluate("/soapenv:Envelope/soapenv:Body/MyNS:myResponse/myReturn", xnm);
前缀是什么并不重要,只要前缀设计的名称空间是相同的

顺便说一句,您应该对SOAP名称空间执行同样的操作,因为您的XPath查询基于前缀,并且可以生成完全相同的XML,其中具有针对相同名称空间的不同前缀

我会写一些更健壮的东西,适用于不同的SOAP生成器,比如

string response = GetXMLString();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(response);
XmlNamespaceManager xnm = new XmlNamespaceManager(xmlDocument.NameTable);
xnm.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
xnm.AddNamespace("ns1", "ExampleNS");

xmlDocument.CreateNavigator()
    .Evaluate("/soapenv:Envelope/soapenv:Body/ns1:myResponse/myReturn", xnm);

只添加您事先知道需要执行XPath查询的名称空间怎么样

你可以直接写

xnm.AddNamespace("MyNS", "ExampleNS");
然后

xPathNavigator
    .Evaluate("/soapenv:Envelope/soapenv:Body/MyNS:myResponse/myReturn", xnm);
前缀是什么并不重要,只要前缀设计的名称空间是相同的

顺便说一句,您应该对SOAP名称空间执行同样的操作,因为您的XPath查询基于前缀,并且可以生成完全相同的XML,其中具有针对相同名称空间的不同前缀

我会写一些更健壮的东西,适用于不同的SOAP生成器,比如

string response = GetXMLString();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(response);
XmlNamespaceManager xnm = new XmlNamespaceManager(xmlDocument.NameTable);
xnm.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
xnm.AddNamespace("ns1", "ExampleNS");

xmlDocument.CreateNavigator()
    .Evaluate("/soapenv:Envelope/soapenv:Body/ns1:myResponse/myReturn", xnm);

从不喜欢名称空间在XML中声明的方式,您介绍的案例就是其中之一。无论如何,它的常见做法(可能不是标准做法)是在使用xml之前声明所有名称空间,因此您正在使用的文档可能被视为“已损坏”。从不喜欢名称空间在xml中声明的方式,其中一个是针对您介绍的案例。无论如何,它的常见做法,可能不是一个标准,xml所有名称空间都应该在使用之前声明,因此您使用的文档可能被认为是“损坏的”。这不是一个坏主意,我唯一担心的是,我可以得到的xml文档的类型是相当多样的,我不一定事先知道名称空间是什么,如果不知道请求什么,就不能编写XPath查询。如果知道目标元素的名称,还应该知道其名称空间。这不是一个坏主意,我唯一担心的是,我可以获得的xml文档的类型多种多样,而且我不一定事先知道名称空间是什么。如果不知道要请求什么,就不能编写XPath查询。如果你知道你要定位的元素名,你也应该知道它的名称空间。我实际上不知道确切的.NET实现,但对我来说,导航器的要点是你不必解析整个xml来到达一个节点。虽然这个解决方案有效,但它通过强制进行完整文档解析“扼杀”了导航器上XPath查询请求的概念。这很有效,除非同一级别的多个元素在不同的命名空间下具有相同的本地名称,但这很少发生:)我实际上不知道确切的.NET实现,但对我来说,导航器的要点是,您不必解析整个xml来访问节点。尽管此解决方案有效,但它通过强制进行完整文档解析“消除”了导航器上XPath查询请求的概念。这很有效,除非同一级别上有多个元素在不同命名空间下具有相同的本地名称,但这种情况很少发生:)