如何使用XPath判断一个元素是否存在且不为空?

21

我有一个输入的XML,它在这一行上:

<Holding id="12">
    <Policy>
        <HoldingForm tc="1">Individual</HoldingForm>
        <PolNumber>848433</PolNumber>
        <LineOfBusiness tc="1">Life</LineOfBusiness>
        <CarrierCode>67644</CarrierCode>
    </Policy>
</Holding>

我的XML操作取决于<PolNumber>是否有值(该元素是模式中的可选元素)。我正在使用Mule 3.3 xpath评估器来执行此操作,我的XPath表达式如下:

<expression-filter expression="#[xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]"/> 
只要存在<PolNumber>元素或<PolNumber/>是空元素,这将正常工作。但如果不存在<PolNumber>,上述表达式会抛出异常。我尝试使用XPath boolean函数,但对于<PolNumber/>它返回true。是否有更好的方法来检查元素是否存在且非空?
编辑:这是我的mule配置中命名空间管理器的配置。
<xm:namespace-manager includeConfigNamespaces="true">
    <xm:namespace prefix="acord" uri="http://ACORD.org/Standards/Life/2" />
    <xm:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/encoding/" />
</xm:namespace-manager>
5个回答

30

使用:

boolean(//acord:Holding/acord:Policy/acord:PolNumber/text()[1])

如果//acord:Holding/acord:Policy/acord:PolNumber有第一个文本节点子元素,则产生true(),否则产生false()

请注意:这比计算所有文本节点子元素并将计数与0进行比较更有效率。


我同意这比计算所有文本节点子元素要好,但即使这个解决方案也不是完美的。这个xpath将对<Holding><Policy><PolNumber></PolNumber><Policy></Holding>返回true。我不知道如何在注释中显示新行,但我的意图是在<PolNumber></PolNumber>之间有一个换行符。 - Charu Khurana
2
@学习者,这很简单:boolean(//acord:Holding/acord:Policy/acord:PolNumber/text()[normalize-space()][1]) - Dimitre Novatchev
1
谢谢Dimitre。我对xpath没有接触,这一切对我非常有帮助。 - Charu Khurana

13
你可以使用boolean(...)来检查它是否为空,但要确保查看元素内部
boolean(//PolNumber/node())

如果包含其他节点,这也适用。 如果想限制为文本节点,请使用 text() 替换 node()。您可能希望改用 //text(),则查询还将对 <PolNumber/> 的其他子元素内的文本节点返回 true。


在我看来,这应该是被接受的答案。在 <a></a> 上使用 boolean(//a/node()) 会返回 false。而在 <a><b/></a> 上则返回 true。你可以在这里尝试一下:https://www.freeformatter.com/xpath-tester.html。在这两种情况下,`boolean(//a/text()[1])` 都会返回 false。 - JGFMK

3
也许我有点晚了,但这里的答案有点令人困惑。当文本为空或只包含空格而没有字符时,此代码将始终返回false。
boolean//Holding/Policy/PolNumber/child/text()[normalize-space()]

2

使用count来获取文本节点的数量如何?

<expression-filter
    expression="#[xpath('count(//Holding/Policy/PolNumber/child::text())') != 0]"/>

感谢您的回复。对于count函数,抛出了“No Such Function {http://www.mulesoft.org/schema/mule/core}:count (org.jaxen.UnresolvableException) org.jaxen.SimpleFunctionContext:127”异常。 - Charu Khurana
奇怪的是你必须使用 fn 前缀。请编辑你的问题并展示你的命名空间管理器配置。 - David Dossot
2
谢谢,我认为 includeConfigNamespaces 就是导致默认命名空间出现问题并强制前缀为 fn 的原因。你真的需要它吗? - David Dossot
我已经检查了我的答案,以计算PolNumber中文本子节点的数量。您可能需要在配置中加上fn:前缀。 - David Dossot
现在,拥有文本子节点,它适用于所有场景。非常感谢。 - Charu Khurana
显示剩余2条评论

2

你觉得这样的表达方式如何:expression="#[?xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]"?这个表达式在所有情况下都应该有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接