嵌套 for-each 循环,从内部循环访问带有变量的外部元素 [英] Nested for-each loops, accessing outer element with variable from the inner loop

查看:66
本文介绍了嵌套 for-each 循环,从内部循环访问带有变量的外部元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个 XSL,它将从源 XML 输出特定的字段子集.该子集将在转换时通过使用包含字段名称和其他特定信息(例如填充长度)的外部 XML 配置文档来确定.

所以,这是两个 for-each 循环:

  • 外层遍历记录以逐条记录访问它们的字段.
  • 内部循环遍历配置 XML 文档以从当前记录中获取配置的字段.

我在 在 XSLT 中看到如何从嵌套循环内访问外部循环中的元素?外部循环中的当前元素可以存储在 xsl:variable 中.但是我必须在内循环中定义一个新变量来获取字段名称.这就引出了一个问题:是否可以访问包含两个变量的路径?

例如,源 XML 文档如下所示:

<数据集><记录><field1>value1</field1>...<fieldN>valueN</fieldN></记录></数据集><数据集><记录><field1>value1</field1>...<fieldN>valueN</fieldN></记录></数据集></数据>

我想要一个像这样的外部 XML 文件:

<预><代码><配置><outputField order="1"><fieldName>field1</fieldName><fieldPadding>25</fieldPadding></outputField>...<outputField order="N"><fieldName>fieldN</fieldName><fieldPadding>10</fieldPadding></outputField></配置>

到目前为止我得到的 XSL:

<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="padding" select="fieldPadding"/><!-- 麻烦来了--><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 很陌生,所以这很可能是一个荒谬的问题,而且该方法也可能是完全错误的(即,对于可以在开始时完成的任务,重复内部循环).我很感激有关如何从外循环元素中选择字段值的任何提示,当然,我愿意接受更好的方法来处理此任务.

解决方案

您的样式表看起来几乎没问题.只是表达式 $rec/$field 没有意义,因为您不能以这种方式组合两个节点集/序列.相反,您应该使用 name() 函数比较元素的名称.如果我正确理解您的问题,这样的事情应该可以工作:

<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() 访问内部循环的当前上下文节点:

I'm trying to write an XSL that will output a certain subset of fields from the source XML. This subset will be determined at transformation time, by using an external XML configuration document containing the field names, and other specific information (such as the padding length).

So, this is two for-each loops:

  • The outer one iterates over the records to access their fields record by record.
  • The inner one iterates over the configuration XML document to grab the configured fields from the current record.

I've seen in In XSLT how do I access elements from the outer loop from within nested loops? that the current element in the outside loop can be stored in an xsl:variable. But then I've got to define a new variable inside the inner loop to get the field name. Which yields to the question: Is it possible to access a path in which there are two variables ?

For instance, the source XML document looks like:

<data>
    <dataset>
        <record>
            <field1>value1</field1>
            ...
            <fieldN>valueN</fieldN>
        </record>
    </dataset>
    <dataset>
        <record>
            <field1>value1</field1>
            ...
            <fieldN>valueN</fieldN>
        </record>
    </dataset>
</data>

I'd like to have an external XML file looking like:

<configuration>
    <outputField order="1">
        <fieldName>field1</fieldName>
        <fieldPadding>25</fieldPadding>
    </outputField>
    ...
    <outputField order="N">
        <fieldName>fieldN</fieldName>
        <fieldPadding>10</fieldPadding>
    </outputField>
</configuration>

The XSL I've got so far:

<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>

I'm quite new to XSL, so this might well be a ridiculous question, and the approach can also be plain wrong (i.e. repeatig inner loop for a task that could be done once at the beggining). I'd appreciate any tips on how to select the field value from the outer loop element and, of course, open to better ways to approach this task.

解决方案

Your stylesheet looks almost fine. Just the expression $rec/$field doesn't make sense because you can't combine two node sets/sequences this way. Instead, you should compare the names of the elements using the name() function. If I understood your problem correctly, something like this should work:

<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>

Variable field is not required in this example. You can also use function current() to access the current context node of the inner loop:

<xsl:variable name="value" select="$rec/*[name(.)=current()/fieldName]"/>

这篇关于嵌套 for-each 循环,从内部循环访问带有变量的外部元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆