Bucles for-each anidados, accediendo al elemento exterior con variable desde el bucle interior

Estoy tratando de escribir un XSL que generará un determinado subconjunto de campos del XML de origen. Este subconjunto se determinará en el momento de la transformación mediante el uso de un documento de configuración XML externo que contenga los nombres de los campos y otra información específica (como la longitud del relleno).

Entonces, esto es dos for-each bucles:

  • El exterior itera sobre los registros para acceder a sus campos registro por registro.
  • El interno itera sobre el documento XML de configuración para obtener los campos configurados del registro actual.

He visto en En XSLT, ¿cómo accedo a los elementos del bucle externo desde dentro de los bucles anidados? que el elemento actual en el bucle exterior se puede almacenar en un xsl:variable. Pero luego tengo que definir una nueva variable dentro del ciclo interno para obtener el nombre del campo. Lo que da lugar a la pregunta: ¿Es posible acceder a un camino en el que hay dos variables?

Por ejemplo, el documento XML de origen se ve así:

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

Me gustaría tener un archivo XML externo con el siguiente aspecto:

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

El XSL que tengo hasta ahora:

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

Soy bastante nuevo en XSL, por lo que esta podría ser una pregunta ridícula, y el enfoque también puede ser simplemente incorrecto (es decir, repetir el ciclo interno para una tarea que podría realizarse una vez al principio). Agradecería cualquier consejo sobre cómo seleccionar el valor de campo del elemento de bucle externo y, por supuesto, abrirme a mejores formas de abordar esta tarea.

preguntado el 03 de mayo de 12 a las 18:05

1 Respuestas

Su hoja de estilo se ve casi bien. solo la expresion $rec/$field no tiene sentido porque no puede combinar dos conjuntos/secuencias de nodos de esta manera. En su lugar, debe comparar los nombres de los elementos usando el name() función. Si entendí tu problema correctamente, algo como esto debería funcionar:

<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 campo no es necesario en este ejemplo. También puede usar la función current() para acceder al nodo de contexto actual del bucle interno:

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

contestado el 03 de mayo de 12 a las 18:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.