XSLT:带有扩展值的Xpath查询返回"节点存在"当没有这样的节点时

时间:2017-06-09 09:41:36

标签: xml xslt

请考虑以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:template name="getServiceDef">
        <services>
            <service>
                <serviceName>service</serviceName>
                <parameters>
                    <param1/>
                    <param2/>
                    <param3/>
                </parameters>
            </service>
        </services>
    </xsl:template>

    <xsl:template name="getInput">
        <parameters>
            <param1>10</param1>
            <param2>single</param2>
            <param3>2</param3>
            <param4>650</param4>
            <param5>750</param5>
        </parameters>
    </xsl:template>

    <xsl:template match="/">
        <xsl:variable name="serviceDef">
            <xsl:call-template name="getServiceDef"/>
        </xsl:variable>
        <xsl:variable name="inputParameters">
            <xsl:call-template name="getInput"/>
        </xsl:variable>

        <xsl:for-each select="$inputParameters/parameters/param4">
            <xsl:variable name="currentParameterName" select="./local-name()"/>
            <xsl:choose>
                <xsl:when test="$serviceDef/services/service/parameters/$currentParameterName">
                    <xsl:message>
                        $currentParameterName '<xsl:value-of select="$currentParameterName"/>'exists.
                        $serviceDef/services/service/parameters/param4 '<xsl:value-of select="$serviceDef/services/service/parameters/param4"/>'
                        $serviceDef/services/service/parameters/$currentParameterName '<xsl:value-of select="$serviceDef/services/service/parameters/$currentParameterName"/>' 
                    </xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:message>param '<xsl:value-of select="$currentParameterName"/>' does NOT exist</xsl:message>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

以行

开头的代码块
<xsl:for-each select="$inputParameters/parameters/param4"> 

我试图决定,$ serviceDef中是否存在节点。它不是。但是,如果使用扩展变量执行XPATH查询,则查询将被评估为&#34;节点存在&#34; (下面的控制台输出)。

问题: 为何查询 $ serviceDef / services / service / parameters / param4返回&#34; False&#34;和 $ serviceDef / services / service / parameters / $ currentParameterName返回&#34; True&#34; ? 我希望查询完全相同。

要复制:

  1. 将上面的代码复制到文件stackOverFlowReplication.xsl

  2. 笔记本电脑:〜$ echo&#34;&lt; notneeded /&gt;&#34; &GT; sample.xml中

  3. laptop:〜$ java -jar saxon9pe.jar -s:sample.xml -xsl:stackOverFlowReplication.xsl
  4. 控制台输出:

    No license file found - running with licensable features disabled
    Warning at xsl:stylesheet on line 2 column 125 of stackOverFlowReplication.xsl:
      Running an XSLT 10 stylesheet with an XSLT 20 processor
    
            $currentParameterName 'param4'exists.
            $serviceDef/services/service/parameters/param4 ''
            $serviceDef/services/service/parameters/$currentParameterName 'param4' 
    

1 个答案:

答案 0 :(得分:1)

您似乎期望test="$serviceDef/services/service/parameters/$currentParameterName"在运行时根据您在最后一步中插入的变量构造XPath表达式。这不会发生,您只需在最后一步中评估变量引用$currentParameterName,并评估字符串param4和布尔上下文中的任何非空字符串,如xsl:when/xsl:if test评估为真。

您需要使用XSLT 3.0中提供的xsl:evaluate进行动态XPath评估,或者对于您可以使用的简单案例,例如test="$serviceDef/services/service/parameters/*[local-name() = $currentParameterName]"

为了让您了解表达式的评估结果,请参阅http://xsltransform.net/naZXpX1

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs fo">
    <xsl:template name="getServiceDef">
        <services>
            <service>
                <serviceName>service</serviceName>
                <parameters>
                    <param1/>
                    <param2/>
                    <param3/>
                </parameters>
            </service>
        </services>
    </xsl:template>

    <xsl:template name="getInput">
        <parameters>
            <param1>10</param1>
            <param2>single</param2>
            <param3>2</param3>
            <param4>650</param4>
            <param5>750</param5>
        </parameters>
    </xsl:template>

    <xsl:template match="/">
        <xsl:variable name="serviceDef">
            <xsl:call-template name="getServiceDef"/>
        </xsl:variable>
        <xsl:variable name="inputParameters">
            <xsl:call-template name="getInput"/>
        </xsl:variable>

        <xsl:for-each select="$inputParameters/parameters/param4">
            <xsl:variable name="currentParameterName" select="./local-name()"/>
            <xsl:variable name="exp1" select="$serviceDef/services/service/parameters/$currentParameterName"/>
            <debug-help string-sequence-test="{$exp1 instance of xs:string*}" node-sequence-test="{$exp1 instance of node()*}" value="{$exp1}"/>

        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出<debug-help string-sequence-test="true" node-sequence-test="false" value="param4"/>所以它显示你从来没有一个节点序列,只是一个带有你的变量值的单个字符串的序列。