2012-09-18 92 views
5

He creado un XSLT y me preguntaba cómo es posible copiar todos los nodos entre un conjunto de etiquetas, y agregar otra etiqueta en la parte inferior. Creé el XSLT que tiene toda la lógica para determinar qué etiqueta agregar y cómo se debe llamar. Sin embargo, el problema que estoy recibiendo ahora es que no puedo copiar todas las otras etiquetas también. A continuación se presentan los archivos en cuestión:XSLT - Copie todos los otros nodos, agregue 1 nuevo nodo

XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/csvImportSchema"> 
     <csvImportSchema> 
      <xsl:for-each select="payload"> 
       <payload> 
        <xsl:copy-of select="@*"/> 
        <xsl:variable name="ean"> 
         <xsl:value-of select="ean"/> 
        </xsl:variable> 
        <xsl:for-each select="../product"> 
         <xsl:if test="ean = $ean"> 
          <productId><xsl:value-of select="article"/></productId> 
         </xsl:if> 
        </xsl:for-each> 
       </payload> 
      </xsl:for-each> 
     </csvImportSchema> 
    </xsl:template> 

</xsl:stylesheet> 

ENTRADA

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

CORRIENTE DE SALIDA

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

salida deseada

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Respuesta

7

Este breve y simple transformación:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="productId"> 
    <productId> 
    <xsl:value-of select="../../product/article"/> 
    </productId> 
</xsl:template> 
<xsl:template match="product"/> 
</xsl:stylesheet> 

cuando se aplica en el documento XML proporcionado:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

produce el, resultado correcto deseada:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Explicación:

  1. Los identity rule copias "tal cual" cada nodo para el que se ha seleccionado para su ejecución.

  2. Una plantilla que coincida con product "borra" este elemento de la salida (por su cuerpo vacío).

  3. Otra plantilla primordial coincide con productId y genera este elemento con un elemento secundario de texto-nodo tomado de product/article.

1

Debe ser tan simple como cambiar su carga útil xsl:copy-of select="@*"/ a

<xsl:copy-of select="*[local-name() != 'productId'] | @*"/> 

es decir, copiar todo, excepto productId, porque se construye esto manualmente.

Esto le da a la salida que ha requerido

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
    <test>1</test> 
    <test2>2</test2> 
    <test3>3</test3> 
    <ean>1111111111</ean> 
    <productId>722619</productId> 
    </payload> 
</csvImportSchema> 
1

Este XSLT debe hacer el trabajo y usos manera más etiquetas copiar y plantillas. Tal vez no haga todo en una plantilla xsl: (mi opinión).

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/csvImportSchema"> 
     <xsl:copy> 
      <xsl:apply-templates select="*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/payload/productId"> 
     <xsl:variable name="ean"> 
      <xsl:value-of select="../ean"/> 
     </xsl:variable> 
     <xsl:for-each select="../../product"> 
      <xsl:if test="ean = $ean"> 
       <productId><xsl:value-of select="article"/></productId> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/product"> 
     <!-- do not copy --> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/payload"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
2

Una observación en su código. No utilice este:

<xsl:variable name="ean"> 
    <xsl:value-of select="../ean"/> 
</xsl:variable> 

cuando se podría escribir lo siguiente:

<xsl:variable name="ean" select="../ean"/> 

No sólo es prolijo, también es muy ineficiente: en lugar de $ ean unirse a un nodo existente, que está extrayendo el valor de cadena de un nodo existente, formando un nodo de texto con ese valor de cadena, creando un nuevo árbol de documento XML y agregando este nodo de texto al contenido de este nuevo documento. (Una vez conseguí una hoja de estilo para ejecutar 3 veces más rápido al eliminar esta horrible construcción.)

+0

Gracias. Lo tendré en cuenta. – MMKD

Cuestiones relacionadas