我使用此xpath表达式列出所有"NON TEST"项:
/Items/Item[State!='TEST']/Name
Run Code Online (Sandbox Code Playgroud)
通常输入XML看起来像这样,一切正常:
<Items>
<Item>
<Name>Item1</Name>
<State>ACTIVE</State>
</Item>
<Item>
<Name>Item2</Name>
<State>TEST</State>
</Item>
</Items>
Run Code Online (Sandbox Code Playgroud)
但是当Item miss State元素时,xpath表达式什么都不选:
<Items>
<Item>
<Name>Item1</Name>
</Item>
<Item>
<Name>Item2</Name>
</Item>
</Items>
Run Code Online (Sandbox Code Playgroud)
请问,我应该如何更改我的xpath表达式,以便在State元素不存在时它也能正常工作?如果State元素不存在,则Item被视为"NON TEST"项.我没有选择改变xml结构.
使用以下表达式:
/Items/Item[not(State='TEST')]/Name
Run Code Online (Sandbox Code Playgroud)
不同之处在于State!='TEST'选择具有State字符串值不等于的任何元素的那些项目TEST,同时not(State='TEST')选择所有没有State字符串值等于的元素的项目TEST(无论是否State存在).这是一个微妙但重要的区别.
从规格:
如果要比较的一个对象是节点集而另一个是字符串,那么当且仅当节点集中有节点时才进行比较,以便对字符串值执行比较的结果节点和另一个字符串是真的.
此外,想象以下输入:
<Items>
<Item>
<Name>Item1</Name>
<State>blah</State>
<State>TEST</State>
</Item>
<Item>
<Name>Item2</Name>
<State>TEST</State>
</Item>
</Items>
Run Code Online (Sandbox Code Playgroud)
这个表达式:
/Items/Item[State!='TEST']/Name
Run Code Online (Sandbox Code Playgroud)
...将选择第一Item的Name元件,因为它包含至少一种 State不具有值元件TEST.
但是,这个表达式:
/Items/Item[not(State='TEST')]/Name
Run Code Online (Sandbox Code Playgroud)
...不选择任何物品.第二种形式通常是你想要的.
请参阅规范中的此注释:
注意:如果
$x绑定到节点集,$x="foo"则不等同于not($x!="foo"):当且仅当某个节点$x具有字符串值时foo,前者才为真; 当且仅当所有 节点$x都具有字符串值时,后者才是真的foo.