You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何动态生成/修改XSLT参数名以批量传递Java参数?

问题描述

我正尝试借助XSLT模板生成XML,需要生成若干标签相同但内部值不同的元素。现有XSLT样式代码如下:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="NbOfBatches"/>
    <xsl:param name="wholeTag"/>
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <Document xmlns="urn:something" xmlns:file="someUrn">
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="$NbOfBatches"></xsl:value-of></file:NbOfBatches>
                <xsl:call-template name="selects">
                    <xsl:with-param name="i">1</xsl:with-param>
                    <xsl:with-param name="count"><xsl:value-of select="$NbOfBatches"/></xsl:with-param>
                </xsl:call-template>
            </FileAppHdr>
        </Document>
    </xsl:template>

    <xsl:template name="selects">
        <xsl:param name="i" />
        <xsl:param name="count" />

        <xsl:if test="$i &lt;= $count">
            <xsl:call-template name="credit">
                <xsl:with-param name="param0"/>
            </xsl:call-template>
        </xsl:if>

        <xsl:if test="$i &lt;= $count">
            <xsl:call-template name="selects">
                <xsl:with-param name="i">
                    <xsl:value-of select="$i + 1"/>
                </xsl:with-param>
                <xsl:with-param name="count">
                    <xsl:value-of select="$count"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="credit">
        <xsl:param name="param0"/>
        <CreditTransfer>
            <xsl:value-of select="$param0"/>
        </CreditTransfer>
    </xsl:template>
</xsl:stylesheet>

目前可通过Saxon或JAXP调用.setParameter()传入NbOfBatches参数控制生成标签数量,但希望能动态生成/修改CreditTransfer中的param0参数名,以便在Java中循环调用.setParameter("param1", value1)、.setParameter("param2", value2)等传递不同参数值。

解决方案

方法1:使用参数集合(推荐,XSLT 2.0+兼容)

如果使用Saxon支持的XSLT 2.0及以上版本,建议直接传递值序列作为单个参数,避免逐个命名param1、param2,代码更简洁易维护:

修改后的XSLT代码

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="NbOfBatches" as="xs:integer"/>
    <!-- 接收值序列参数 -->
    <xsl:param name="CreditValues" as="xs:string*"/>
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <Document xmlns="urn:something" xmlns:file="someUrn">
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="$NbOfBatches"/></file:NbOfBatches>
                <!-- 直接遍历值序列生成元素 -->
                <xsl:for-each select="$CreditValues[position() le $NbOfBatches]">
                    <CreditTransfer>
                        <xsl:value-of select="."/>
                    </CreditTransfer>
                </xsl:for-each>
            </FileAppHdr>
        </Document>
    </xsl:template>
</xsl:stylesheet>

Java调用示例

// 假设使用Saxon的Processor
Processor processor = new Processor(false);
XsltCompiler compiler = processor.newXsltCompiler();
XsltExecutable executable = compiler.compile(new File("your-style.xsl"));
XsltTransformer transformer = executable.load();

// 构造值序列
List<String> creditValues = Arrays.asList("value1", "value2", "value3");
// 传递序列参数
transformer.setParameter(new QName("CreditValues"), processor.newArray(creditValues.stream().map(processor::newStringValue).toArray(XdmValue[]::new)));

// 执行转换(省略输出逻辑)

方法2:动态查找命名参数(XSLT 1.0兼容,依赖Saxon扩展)

如果必须保留逐个命名param1、param2的方式,可以借助Saxon的扩展函数动态获取参数值:

修改后的XSLT代码

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:saxon="http://saxon.sf.net/"
                extension-element-prefixes="saxon">
    <xsl:param name="NbOfBatches"/>
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <Document xmlns="urn:something" xmlns:file="someUrn">
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="$NbOfBatches"/></file:NbOfBatches>
                <xsl:call-template name="selects">
                    <xsl:with-param name="i">1</xsl:with-param>
                    <xsl:with-param name="count" select="$NbOfBatches"/>
                </xsl:call-template>
            </FileAppHdr>
        </Document>
    </xsl:template>

    <xsl:template name="selects">
        <xsl:param name="i" />
        <xsl:param name="count" />

        <xsl:if test="$i &lt;= $count">
            <!-- 动态构造参数名,比如param1、param2 -->
            <xsl:variable name="paramName" select="concat('param', $i)"/>
            <CreditTransfer>
                <!-- 使用Saxon扩展获取参数值 -->
                <xsl:value-of select="saxon:evaluate(concat('$', $paramName))"/>
            </CreditTransfer>
            <!-- 递归调用 -->
            <xsl:call-template name="selects">
                <xsl:with-param name="i" select="$i + 1"/>
                <xsl:with-param name="count" select="$count"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Java调用示例

// 使用Saxon的TransformerFactory
TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl();
Transformer transformer = factory.newTransformer(new StreamSource("your-style.xsl"));

int nbOfBatches = 3;
transformer.setParameter("NbOfBatches", String.valueOf(nbOfBatches));
// 循环设置param1到paramN
for (int i = 1; i <= nbOfBatches; i++) {
    transformer.setParameter("param" + i, "value" + i);
}

// 执行转换(省略输出逻辑)

方法3:XSLT 1.0节点集参数(兼容旧版处理器)

如果只能用XSLT 1.0且不能用Saxon扩展,可以传递XML节点集作为参数:

Java端构造节点集

// 构造包含所有值的XML片段
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
Element root = doc.createElement("Values");
for (int i = 1; i <= nbOfBatches; i++) {
    Element value = doc.createElement("Value");
    value.setTextContent("value" + i);
    root.appendChild(value);
}
// 设置参数,将节点集传入
transformer.setParameter("CreditValues", root);

修改后的XSLT代码

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="NbOfBatches"/>
    <xsl:param name="CreditValues"/>
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <Document xmlns="urn:something" xmlns:file="someUrn">
            <FileAppHdr>
                <file:NbOfBatches><xsl:value-of select="$NbOfBatches"/></file:NbOfBatches>
                <xsl:for-each select="$CreditValues/Value[position() &lt;= $NbOfBatches]">
                    <CreditTransfer>
                        <xsl:value-of select="."/>
                    </CreditTransfer>
                </xsl:for-each>
            </FileAppHdr>
        </Document>
    </xsl:template>
</xsl:stylesheet>

内容的提问来源于stack exchange,提问作者Priku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:50:26