【发布时间】:2012-09-12 14:51:02
【问题描述】:
我正在尝试使用 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" />
如您所见,在根元素上定义了一些命名空间,但随后定义了ns1。当我尝试评估 xPath 查询 /soapenv:Envelope/soapenv:Body/ns1:myResponse/myReturn 时,我得到一个 XPathException:
Namespace prefix 'ns1' is not defined.
我正在做的是获取 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?
【问题讨论】:
-
从不喜欢在 XML 中声明命名空间的方式,其中之一就是您提出的案例。无论如何,它的常见做法,可能不是标准,xml 所有命名空间都应在使用前声明,因此您正在使用的文档可能被视为“损坏”。