【问题标题】:How to tell using XPath if an element is present and non empty?如何使用 XPath 判断元素是否存在且非空?
【发布时间】:2013-04-01 07:41:23
【问题描述】:

我在这一行有一个输入 XML:

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

我对此 XML 的操作取决于&lt;PolNumber&gt;(它是模式中的可选元素)是否具有值。我正在使用 Mule 3.3 xpath evaluator 执行此操作,我的 XPath 表达式如下所示:

<expression-filter expression="#[xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]"/> 

只要存在&lt;PolNumber&gt; 元素或&lt;PolNumber/&gt; 是空元素,此方法就可以正常工作。但是如果&lt;PolNumber&gt; 不存在,上面的表达式就会抛出异常。

我尝试使用XPath boolean 函数,但它为&lt;PolNumber/&gt; 返回true。有没有更好的方法来检查元素是否存在且非空?

编辑:

这是我的 mule config 中命名空间管理器的配置

<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>

【问题讨论】:

    标签: xml xpath mule


    【解决方案1】:

    使用count获取文本节点数怎么样:

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

    【讨论】:

    • 感谢您的回复。 No Such Function {http://www.mulesoft.org/schema/mule/core}:count (org.jaxen.UnresolvableException) org.jaxen.SimpleFunctionContext:127 count 函数抛出异常。
    • 我将上面的表达式更改为&lt;expression-filter expression="#[xpath('fn:count(//acord:Holding/acord:Policy/acord:PolNumber)') != 0]"/&gt;,但是,&lt;PolNumber/&gt; 计数不为零,就像boolean 函数一样
    • 奇怪的是你必须以fn为前缀。请编辑您的问题并显示您的命名空间管理器是如何配置的。
    • 谢谢,我认为includeConfigNamespaces 搞砸了默认命名空间并强制以fn 为前缀。你真的需要它吗?
    • 我已经通过回答查看了 PolNumber 中文本子节点的数量。您可能需要在配置中添加 fn: 前缀。
    【解决方案2】:

    您可以使用boolean(...) 来检查它是否为空,但请确保查看内部元素。

    boolean(//PolNumber/node())
    

    如果包含其他节点,这也有效。如果要限制为文本节点,请将node() 替换为text()。您可能想改用//text(),然后查询也会为&lt;PolNumber/&gt; 的其他子元素内的文本节点生成true。

    【讨论】:

    • 这在我看来应该是公认的答案。 boolean(//a/node()) on &lt;a&gt;&lt;/a&gt; 给出错误。而&lt;a&gt;&lt;b/&gt;&lt;/a&gt; 则为真。在这里尝试一下:freeformatter.com/xpath-tester.htmlboolean(//a/text()[1]) 在这两种情况下都会产生 false。
    【解决方案3】:

    使用

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

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

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

    【讨论】:

    • 我同意这比计算所有文本节点子节点要好,但即使这个解决方案也不是完全证明的。此 xpath 将为 &lt;Holding&gt;&lt;Policy&gt;&lt;PolNumber&gt;&lt;/PolNumber&gt;&lt;Policy&gt;&lt;/Holding&gt; 返回 true。我不知道如何在评论中显示新行,但我的意图是在 &lt;PolNumber&gt;&lt;/PolNumber&gt; 之间添加新行字符
    • @Learner,这很简单:boolean(//acord:Holding/acord:Policy/acord:PolNumber/text()[normalize-space()][1])
    • 谢谢迪米特。我没有接触过xpath,这一切对我很有帮助。
    【解决方案4】:

    expression="#[?xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]" 怎么样?这应该适用于所有情况

    【讨论】:

      【解决方案5】:

      也许我来晚了,但答案有点混乱。 当文本为空白或有空格但没有字符时,此选项将始终返回 false。

      boolean//Holding/Policy/PolNumber/child/text()[normalize-space()]
      

      【讨论】:

        猜你喜欢
        • 2011-11-02
        • 1970-01-01
        • 1970-01-01
        • 2014-07-18
        • 2011-04-23
        • 1970-01-01
        • 2010-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多