我正在尝试编写一个XSL,它将从源XML输出某个字段子集。通过使用包含字段名称的外部XML配置文档和其他特定信息(例如填充长度),将在转换时确定此子集。
所以,这是两个for-each
循环:
我在In XSLT how do I access elements from the outer loop from within nested loops?中看到外部循环中的当前元素可以存储在xsl:variable
中。但是我必须在内部循环中定义一个新变量来获取字段名称。产生问题的原因是:是否可以访问存在两个变量的路径?
例如,源XML文档如下所示:
<data>
<dataset>
<record>
<field1>value1</field1>
...
<fieldN>valueN</fieldN>
</record>
</dataset>
<dataset>
<record>
<field1>value1</field1>
...
<fieldN>valueN</fieldN>
</record>
</dataset>
</data>
我想要一个外部XML文件,如下所示:
<configuration>
<outputField order="1">
<fieldName>field1</fieldName>
<fieldPadding>25</fieldPadding>
</outputField>
...
<outputField order="N">
<fieldName>fieldN</fieldName>
<fieldPadding>10</fieldPadding>
</outputField>
</configuration>
到目前为止我已经获得了XSL:
<xsl:variable name="config" select="document('./configuration.xml')"/>
<xsl:for-each select="data/dataset/record">
<!-- Store the current record in a variable -->
<xsl:variable name="rec" select="."/>
<xsl:for-each select="$config/configuration/outputField">
<xsl:variable name="field" select="fieldName"/>
<xsl:variable name="padding" select="fieldPadding"/>
<!-- Here's trouble -->
<xsl:variable name="value" select="$rec/$field"/>
<xsl:call-template name="append-pad">
<xsl:with-param name="padChar" select="$padChar"/>
<xsl:with-param name="padVar" select="$value"/>
<xsl:with-param name="length" select="$padding"/>
</xsl:call-template>
</xsl:for-each>
<xsl:value-of select="$newline"/>
</xsl:for-each>
我对XSL很新,所以这可能是一个荒谬的问题,而且这种方法也可能是完全错误的(即重新启动内部循环,可以在开始时完成一次任务)。我很欣赏有关如何从外部循环元素中选择字段值的任何提示,当然,还可以通过更好的方式来完成此任务。
答案 0 :(得分:14)
你的样式表看起来很好。只是表达式$rec/$field
没有意义,因为你不能用这种方式组合两个节点集/序列。相反,您应该使用name()
函数比较元素的名称。如果我理解你的问题,这样的事情应该有效:
<xsl:variable name="config" select="document('./configuration.xml')"/>
<xsl:for-each select="data/dataset/record">
<xsl:variable name="rec" select="."/>
<xsl:for-each select="$config/configuration/outputField">
<xsl:variable name="field" select="fieldName"/>
...
<xsl:variable name="value" select="$rec/*[name(.)=$field]"/>
...
</xsl:for-each>
<xsl:value-of select="$newline"/>
</xsl:for-each>
此示例中不需要变量字段。您还可以使用函数current()
来访问内循环的当前上下文节点:
<xsl:variable name="value" select="$rec/*[name(.)=current()/fieldName]"/>