我使用此xpath表达式列出所有“NON TEST”项:
/Items/Item[State!='TEST']/Name
通常输入XML看起来像这样,一切正常:
<Items>
<Item>
<Name>Item1</Name>
<State>ACTIVE</State>
</Item>
<Item>
<Name>Item2</Name>
<State>TEST</State>
</Item>
</Items>
但是当项目未命中状态元素时,xpath表达式不会选择任何内容:
<Items>
<Item>
<Name>Item1</Name>
</Item>
<Item>
<Name>Item2</Name>
</Item>
</Items>
请问,我应该如何更改我的xpath表达式,以便在State元素不存在时它也能正常工作?如果State元素不存在,则Item被视为“NON TEST”项。我没有选择改变xml结构。
答案 0 :(得分:5)
使用以下表达式:
/Items/Item[not(State='TEST')]/Name
不同之处在于State!='TEST'
选择具有任何State
元素且其字符串值不等于TEST
的项目,而not(State='TEST')
选择所有没有State
的项目1}}字符串值等于TEST
的元素(是否存在State
)。这是一个微妙但重要的区别。
来自the spec:
如果要比较的一个对象是节点集而另一个是字符串, 那么当且仅当有一个节点时,比较才会成立 node-set使得执行比较的结果 节点的字符串值和另一个字符串为真。
此外,想象一下以下输入:
<Items>
<Item>
<Name>Item1</Name>
<State>blah</State>
<State>TEST</State>
</Item>
<Item>
<Name>Item2</Name>
<State>TEST</State>
</Item>
</Items>
这个表达式:
/Items/Item[State!='TEST']/Name
...将选择第一个Item
的{{1}}元素,因为它包含至少一个 Name
元素,其值不是{{ 1}}。
但是,这个表达式:
State
...不选择任何物品。第二种形式通常是你想要的。
请参阅此说明from the spec:
注意:如果
TEST
绑定到节点集,那么/Items/Item[not(State='TEST')]/Name
并不意味着 与$x
相同:当且仅当某些节点时,前者才是真的$x="foo"
具有字符串值not($x!="foo")
;当且仅当 all 时,后者才是真的$x
中的节点具有字符串值foo
。