2012-05-03 23 views
13

Estoy intentando escribir un XSL que generará un cierto subconjunto de campos desde el código fuente XML. Este subconjunto se determinará en el momento de la transformación, utilizando 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).Anidados para cada bucle, accediendo al elemento externo con variable desde el bucle interno

Por lo tanto, se trata de dos bucles for-each:

  • se repite el exterior uno más de los registros para acceder a su registro de campos por registro.
  • El interno itera sobre el documento XML de configuración para tomar los campos configurados del registro actual.

que he visto en In XSLT how do I access elements from the outer loop from within nested loops? que el elemento corriente en el bucle exterior puede ser almacenada en un xsl:variable. Pero luego tengo que definir una nueva variable dentro del ciclo interno para obtener el nombre del campo. Lo que nos lleva a la pregunta: ¿es posible acceder a un camino en el que hay dos variables?

Por ejemplo, el documento XML de origen se parece a:

<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 que parece:

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

El XSL Tengo hasta el momento:

<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 a XSL, por lo que esta bien podría ser una pregunta ridícula, y el enfoque también puede ser liso WRO ng (es decir repeatig loop interno para una tarea que podría hacerse una vez al principio). Agradecería cualquier consejo sobre cómo seleccionar el valor de campo del elemento de ciclo externo y, por supuesto, abrir a mejores formas de abordar esta tarea.

Respuesta

13

Su hoja de estilo se ve casi bien. Solo la expresión $rec/$field no tiene sentido porque no puede combinar dos conjuntos de nodos/secuencias de esta manera. En su lugar, debe comparar los nombres de los elementos utilizando la función name(). Si he entendido correctamente su problema, 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]"/> 
Cuestiones relacionadas