XPath名称空间通配符最佳实践

时间:2015-04-16 11:19:03

标签: xml xpath

在我们的例子中,我们有像这样的动态XML标记

<ab:SomeProcessResponse xmlns:ab="http://something.com/xyz"
                        xmlns:cd="http://something.com/lmno">

或者有时我可能会得到回应

<def:SomeProcessResponse xmlns:def="http://something.com/xyz"
                         xmlns:cd="http://something.com/lmno">

在这种情况下,我应该选择节点SomeProcessResponse时应遵循的最佳做法是什么?

3 个答案:

答案 0 :(得分:4)

选择命名空间XML元素的最佳做法是指定命名空间, not 通过任何类型的&#34;通配符&#34;来忽略它。机构。

对于兼容的XPath处理器,始终存在一种机制,允许将名称空间前缀(例如:ab)绑定到名称空间URI(例如:http://something.com/xyz)。甚至不必使用与源XML中使用的相同的名称空间前缀(ab);只有名称空间URI(http://something.com/xyz)必须匹配。然而,唯一的挑战是XPath本身没有将名称空间前缀绑定到名称空间URI的机制。如何操作取决于库提供的功能(例如:libxml2,javax.xml.xpath等)或托管语言(例如:XSLT)。

为了提供纯XPath答案,或者有时因为(通常是非理性的)对命名空间的厌恶,您有时会看到使用的通配符机制。常见的通配符机制是使用local-name()仅引用与命名空间无关的本地名称(例如:SomeProcessResponse)。这样做的问题是它不仅绕过名称空间前缀(例如:ab),还绕过名称空间URI(http://something.com/xyz),名称空间URI是名称的组成部分,也是重要的将其他设施与元素相关联的一部分。例如,此类其他工具包括验证和OO类映射。

所以,是的,有躲避命名空间的通配机制,但最佳做法是使用托管语言/库的工具将命名空间前缀与命名空间URI相关联,通过通配符来避免名称空间

答案 1 :(得分:2)

这里不需要“通配符”,因为两个示例都是相同的XML - 具有本地名称SomeProcessResponse和名称空间URI http://something.com/xyz的元素。它们使用两个不同的前缀这一事实无关紧要,XPath表达式中使用的前缀绑定由XPath库决定,不必与文档中使用的前缀绑定相匹配。

您需要使用XPath库提供的工具将xyz之类的前缀绑定到http://something.com/xyz命名空间URI,然后xyz:SomeProcessResponse的XPath将匹配这两个示例。

为了给出更具体的答案,我需要知道您正在使用哪种编程语言和哪种XPath API。


编辑:在您的评论中,您说您正在使用JavaScript - 在这种情况下,您可以通过将函数传递给document.evaluate

来提供命名空间绑定
var result = document.evaluate("//xyz:SomeProcessResponse", document, function(prefix) {
  if(prefix == "xyz") {
    return "http://something.com/xyz";
  } else {
    return null;
  }
}, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);

答案 2 :(得分:1)

如果要声明命名空间,则可以正确识别响应。

如果你需要的是xpath来定位元素而不管名称空间,你可以使用它:

//*[local-name()='SomeProcessResponse']

但请记住,对于以下所有情况都是如此:

<ab:SomeProcessResponse xmlns:ab="http://something.com/xyz" xmlns:cd="http://something.com/lmno">
<def:SomeProcessResponse xmlns:def="http://something.com/xyz" xmlns:cd="http://something.com/lmno">
<ab:SomeProcessResponse xmlns:ab="http://somethingCompletelyDifferent.com/xyz">
<SomeProcessResponse>