使用参数作为 XSL 选择语句的参数

Posted

技术标签:

【中文标题】使用参数作为 XSL 选择语句的参数【英文标题】:Using a param as the argument to XSL select statement 【发布时间】:2021-08-01 07:55:33 【问题描述】:

我正在使用 apache fop 生成 PDF,我有一个生成表格的 XSL-FO 模板,我希望能够使用不同的选择参数多次调用该模板。

这是我的 xsl 样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
                version="1.0">
    <xsl:output method="html"/>

    <xsl:template name="checklist">
        <xsl:param name="H1"/>
        <xsl:param name="H2"/>
        <xsl:param name="H3"/>
        <xsl:param name="src"/>
        <fo:block  >
            <fo:table  font-size="8pt" table-layout="fixed" >
                <fo:table-column column-/>
                <fo:table-column column-/>
                <fo:table-column column-/>
                <fo:table-header font-weight="bold" background-color="lightgrey">
                    <fo:table-row>
                        <fo:table-cell>
                            <fo:block><xsl:value-of select="$H1"/></fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block text-align="center"><xsl:value-of select="$H2"/></fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block><xsl:value-of select="$H3"/></fo:block>
                        </fo:table-cell>
                    </fo:table-row>
                </fo:table-header>
                <fo:table-body>

                    <xsl:apply-templates select="$src" />

                </fo:table-body>
            </fo:table>
        </fo:block>
    </xsl:template>

    <xsl:template match="item">
        <fo:table-row line-stacking-strategy="line-height" margin="0mm" space-before="1mm" background-color="white">
            <xsl:variable name="hdr" select="hdr"/>
            <xsl:choose>
                <xsl:when test="$hdr = 'y'">
                    <fo:table-cell number-columns-spanned="3" background-color="lightgrey" border="1px solid #b8b6b6">
                        <fo:block>
                            <fo:inline>
                                <xsl:value-of select="id"/>&#x00A0;
                                <xsl:value-of select="description"/>
                            </fo:inline>
                        </fo:block>
                    </fo:table-cell>
                </xsl:when>
                <xsl:otherwise>
                    <fo:table-cell border="1px solid #b8b6b6" vertical-align="middle" text-align="center">
                        
                        <fo:block line->
                            <xsl:value-of select="id"/>
                        </fo:block>
                    </fo:table-cell>
                    <fo:table-cell border="1px solid #b8b6b6" padding-left="3pt">
                        <fo:block>
                            <xsl:value-of select="description"/>
                        </fo:block>
                    </fo:table-cell>
                    <fo:table-cell border="1px solid #b8b6b6" text-align="center" padding-right="3pt">
                        <xsl:variable name="outcome" select="outcome"/>
                        <fo:block color="white">
                            <!--<fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/c1.svg"   content- content-/>-->
                            <xsl:choose>
                                <xsl:when test="$outcome = 'ok'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/c1n.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'c1'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/ok.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'c2'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/c2.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'c3'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/c3.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'fi'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/fi.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'nv'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/nv.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'na'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/na.svg" vertical-align="middle"    content-/>
                                </xsl:when>
                                <xsl:when test="$outcome = 'lim'">
                                    <fo:external-graphic src="file:///F:/Projects/Active/eCert/src/resources/lim.svg" vertical-align="middle"  content-/>
                                </xsl:when>
                            </xsl:choose>
                        </fo:block>
                
                    </fo:table-cell>
                </xsl:otherwise>
            </xsl:choose>
        </fo:table-row>
    </xsl:template>

</xsl:stylesheet>

这是调用模板的流程之一

<fo:flow flow-name="xsl-region-body">
                    <fo:block />
                    <xsl:call-template name="checklist">
                        <xsl:with-param name="H1" select="'Item No.'"/>
                        <xsl:with-param name="H2" select="'Description'"/>
                        <xsl:with-param name="H3" select="'Outcome'"/>
                        <xsl:with-param name="src" select="'eicr/checklist/item'"/>
                        
                    </xsl:call-template>
                        
                </fo:flow>

当我执行 FOP 时,我收到以下错误 ** 无法将 #STRING 转换为 NodeList!** 参数 H1、H2 和 H3 用作列标题,该部分工作正常 src 参数应该用于从 xml 列表中选择项目。

我是新的 xsl fo,所以任何可以帮助我实现预期结果的帮助或文档指针都将不胜感激。

非常感谢

【问题讨论】:

您的错误很可能在这里: “src” 表示从外部传递到 XSLT 的参数。这始终是一个字符串。您需要使用 xslt 扩展将字符串“src”解析为节点集之前 @KevinBrown 在上面的代码中,$src 是内部传递给被调用模板的参数——它可以是任何数据类型。 你是对的。需要在电脑上而不是手机上阅读这些内容。 【参考方案1】:

删除eicr/checklist/item 周围的单引号。 'eicr/checklist/item' 是字符串文字; eicr/checklist/item 是一个位置路径,它将选择相对于上下文节点的元素。


我试图避免的替代方法(因为它更冗长)是在调用模板之前或作为调用模板的一部分应用模板,然后将结果复制到结果树:

<xsl:with-param name="src">
   <xsl:apply-templates select="eicr/checklist/item" />
</xsl:with-param>
<fo:table-body>
  <xsl:copy-of select="$src" />
</fo:table-body>

这是您在 DocBook XSLT 1.0 样式表中看到的一种技术,例如:

https://github.com/docbook/xslt10-stylesheets/blob/6ff683948c5a85949e4b7661f302e8b5f12f7bf2/xsl/fo/block.xsl#L181

【讨论】:

我试过不带单引号 仍然得到同样的错误严重:org.xml.sax .SAXParseException;行号:0;列号:0;无法将 #STRING 转换为 NodeList! @JReynolds,你继续得到同样的错误似乎很奇怪。在 cmets 中解决问题总是很困难,因为您可以随时编辑您的问题并在此处以详细且格式良好的方式提供更多信息。因此,也许将新信息添加到您的问题中。另外,行号真的是0吗?是否没有说明是哪一行或哪条语句导致了错误?

以上是关于使用参数作为 XSL 选择语句的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何在选择语句的“NOT IN”子句中使用逗号分隔的字符串列表作为 pl/sql 存储的函数参数

XSL以xsl param作为参数运行

XSL/FO 在选择语句中跳过一个值

Saxon-HE Java 扩展 - 如何访问作为参数传递的 xsl 变量的值?

将表作为参数传递给函数

创建节点集并作为参数传递