有条件地分配变量以匹配 xslt 模板中的路径

Conditionaly assign variable to match path in xslt template

我想在 xslt 模板中动态构建匹配项。我使用 xls fo、apache fop 和 saxon9he。我想以最好的方式从 java 传递参数,但首先我尝试在 xslt.

中设置它

当我像这样创建变量示例时:

<xsl:variable name="testPath" select="/abc:Files/def:Description" /> 

如果我尝试在应用模板中使用它,也能正常工作:

<xsl:apply-templates select="$testPath/qwe:Test"/>

但我想动态设置 testPath 变量。我尝试使用选择标签:

<xsl:variable name="testPath"> 
    <xsl:choose>
        <xsl:when test="$versionNo = '2'">
             <xsl:value-of select="/abc:Files/def:Description" />   
        </xsl:when>
        <xsl:otherwise>
             <xsl:value-of select="/abc:Files/def:Names" /> 
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable> 

但是这种方法不起作用,当我尝试使用这个变量时:

<xsl:apply-templates select="$testPath/qwe:Test"/>

我收到这个错误:

Error evaluating ((attr{table-layout=...}, ...)) on line 82 column 21 of pdf_gen.xsl: SXCH0003: org.apache.fop.fo.ValidationException: "fo:table-body" is missing child elements. Required content model: marker* (table-row+|table-cell+) (See position 82:21):
file:/C:/Users/SuperUser/workspace/project/xls-editor/target/classes/pdf/xsl/pdf_gen.xsl:82:21: "fo:table-body" is missing child elements. Required content model: marker* (table-row+|table-cell+) (See position 82:21)

在最佳选择中,我想将 Java 中的 $testPath 变量作为参数传递,例如:

transformer.setParameter("testPath ", "/abc:Files/def:Description");

并在 xslt 中使用

<xsl:param name="testPath "/>

并在模板中应用:

<xsl:apply-templates select="$testPath/qwe:Test"/>

但我收到以下错误:

Type error evaluating ($testPath) in xsl:apply-templates/@select on line 74 column 60 of pdf_gen.xsl: XPTY0019: The required item type of the first operand of '/' is node(); the supplied value
u"/abc:Files/def:Description" is an atomic value

为什么没有任何解决方案可以实现?

我正在处理类似的问题。 在我看来,变量可见性仅在 <xsl:choose> 块内,我建议您制作模板块并以这种方式调用它们:

<xsl:choose>
    <xsl:when test="$versionNo = '2'" >
        <xsl:call-template name="TemplateOne">
            <xsl:with-param name="testPath" select="'/abc:Files/def:Description'" />
        </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:call-template name="TemplateTwo">
            <xsl:with-param name="testPath" select="'/abc:Files/def:Names'" />
        </xsl:call-template>
    </xsl:otherwise>
</xsl:choose>

模板定义为:

<xsl:template name="TemplateOne">
    <xsl:param name="testPath" />
    ...
    bla bla bla
    remember to use variable in this template as "{$testPath}"
    ...
</xsl:template>

当您使用 Saxon 9 时,您至少会使用 XSLT 2 和 XPath 2,我建议在 XPath 中实现变量选择,例如

<xsl:variable name="testPath" select="if ($versionNo = '2') then /abc:Files/def:Description else /abc:Files/def:Names"/> 

这样你的

<xsl:apply-templates select="$testPath/qwe:Test"/>

应该可以很好地处理先前选择的 def:Descriptiondef:Names 元素的 qwe:Test 个子元素。

当然也可以用例

<xsl:apply-templates select="(if ($versionNo = '2') then /abc:Files/def:Description else /abc:Files/def:Names)/qwe:Test"/>

或者做例如

<xsl:apply-templates select="(/abc:Files/def:Description[$versionNo = '2'], /abc:Files/def:Names[$versionNo != '2'])/qwe:Test"/>