How to select boolean-valued nodes in XPath?

爱⌒轻易说出口 提交于 2020-03-18 14:52:33

问题


I have an XML document and associated schema that defines several attributes as having the xs:boolean type. The lexical values for xs:boolean are true, false, 1, and 0, so it seems that to correctly select attributes with a particular boolean value I'd have to write something like:

@attribute='true' or @attribute='1'

or

@attribute='false' or @attribute='0'

This seems verbose.

You might expect something like boolean(@attribute) to work, but the boolean function has different semantics.

Is there a better way? Is this something that a schema-aware processor would help with?


回答1:


In addition to the solutions proposed by Phil and Tomalak, I discovered that XPath 2.0 provides a few alternatives:

@attribute=('true','1')
string(@attribute) cast as xs:boolean

And finally, XPath 2.0 does provide schema-aware processing, which means that if everything is in alignment, you should be able to write:

data(@attribute)

But schema-aware processors seem hard to come by. The most popular seems to be the non-free commercial variant of saxon, which costs £300. So for now I'm using @attribute=('true','1').




回答2:


Try the following XPath expression:

[@attribute=true()]



回答3:


Your options may depend upon which XPath processor you're using. For example, the Microsoft stuff allows you to define JavaScript functions that you could use to implement the "boolean(@attribute)" pattern. I don't know if other engines may have similar support available.

Otherwise I suspect you are stuck with having to check for both 'true' and '1'.

Hopefully someone else has a better answer.




回答4:


Using XPath alone the expression you propose is as close as it gets. There are different ways of doing the same check, but all of them would lead to a longer and more complicated expression and conceal the intent more.

I don't think there is a schema-aware processor, XML schema is not connected to XSLT and it would not make much sense to build support for it into a processor, IMHO. The language is defined, and extensions are the accepted standard way of adding functionality.

If the library you use supports the EXSL extension functions, you could write a semi-portable mechanism to abstract the boolean check into a function, or you could use vendor-specific extensions like MSXSL to the same.

I think it is best to stay with the expression you have. It is not convoluted, only a bit verbose.




回答5:


I use a simple named template that does the verbose check and tweak it as needed to handle legacy systems (e.g. some fields may use "Y"/"N", some "True"/"False", others 1/0) and dump the value into a variable. It's not the most elegant approach, but if you're using XPath 1.0, don't have EXSLT support, and can't (or don't want to) utilize outside script calls, it works consistently and can be tweaked as needed.

<xsl:template name="CleanupBool">
    <xsl:param name="val" />
    <xsl:choose>
        <xsl:when test="$val='1'">1</xsl:when>
        <xsl:when test="$val='true'">1</xsl:when>
        <xsl:when test="$val='True'">1</xsl:when>
        <xsl:when test="$val='TRUE'">1</xsl:when>
        <xsl:when test="$val='T'">1</xsl:when>
        <xsl:when test="$val='Y'">1</xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:template>

Usage:

<xsl:variable name="enabled">
    <xsl:call-template name="CleanupBool">
        <xsl:with-param name="val" select="IS_ENABLED"/>
    </xsl:call-template>
</xsl:variable>



回答6:


@attribute cast as xs:boolean is a good way to go about it.



来源:https://stackoverflow.com/questions/1117310/how-to-select-boolean-valued-nodes-in-xpath

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!