HLopezRD
HLopezRD

Reputation: 33

XSLT merge/combine nodes

First sorry, maybe this question was already made but I can't find anything to help me, maybe due my lack of knowledge about XSLT.

I have the following XML:

<xml> 
  <EstadoRespuesta>   
    <Error>0</Error>   
    <Estatus>OK</Estatus> 
  </EstadoRespuesta> 
  <NewDataSet>   
    <Table1>
      <Elemento>Cuenta</Elemento>
      <Valor>XZY07633</Valor>   
    </Table1>   
    <Table1>
      <Elemento>Fecha del Balance</Elemento>
      <Valor>2016-Nov-18 19:15</Valor>   
    </Table1>   
    <Table1>
      <Elemento>Balance</Elemento>
      <Valor>60.7</Valor>   
    </Table1>   
    <Table1>
      <Elemento>Lectura</Elemento>
      <Valor>2,152.4</Valor>   
    </Table1>   
    <Table1>
      <Elemento>Suspensión al llegar a</Elemento>
      <Valor>2,213.1</Valor>   
    </Table1>   
    <Table1>
      <Elemento>Fecha aproximada de corte*</Elemento>
      <Valor>2017-Jan-04 15:37</Valor>   
    </Table1> 
  </NewDataSet> 
</xml>

And I want to transform in this:

<xml>
<EstadoRespuesta>
  <Error>0</Error>
  <Estatus>OK</Estatus>
</EstadoRespuesta>
<NewDataSet>
  <Table1>
    <Cuenta>XZY07633</Cuenta>
  </Table1>
  <Table1>
    <FechadelBalance>2016-Nov-18 19:15</FechadelBalance>
  </Table1>
  <Table1>
    <Balance>60.7</Balance>
  </Table1>
  <Table1>
    <Lectura>2,152.4</Lectura>
  </Table1>
  <Table1>
    <Suspensiónalllegara>2,213.1</Suspensiónalllegara>
  </Table1>
  <Table1>
    <Fechaaproximadadecorte>2017-Jan-04 15:37</Fechaaproximadadecorte>
  </Table1>
</NewDataSet>
</xml>

I used this:

<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="/*">
  <records>
    <xsl:apply-templates/>
  </records>
 </xsl:template>

 <xsl:template match="NewDataSet">
  <record>
    <xsl:apply-templates/>
  </record>
 </xsl:template>

<xsl:template match="Table1">
  <record>
    <xsl:apply-templates/>
  </record>
 </xsl:template>

 <xsl:template match="Elemento">
  <xsl:attribute name="local-name(.)">
    <xsl:value-of select="Valor"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

But I'm not closed to get what I need. Can someone give me some advice/help? Thanks in advance.

Upvotes: 3

Views: 170

Answers (2)

zx485
zx485

Reputation: 29052

An XSLT 1.0 solution would be:

<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="/xml">
  <xml>
    <xsl:copy-of select="EstadoRespuesta" />
    <NewDataSet1>
      <xsl:apply-templates select="NewDataSet" />
    </NewDataSet1>
  </xml>
 </xsl:template>

 <xsl:template match="Table1">
  <Table1>
    <xsl:element name="{translate(Elemento,' *ó','')}">
      <xsl:value-of select="Valor" />
    </xsl:element>
  </Table1>
 </xsl:template>
</xsl:stylesheet>

Its result is

<xml>
    <EstadoRespuesta>
        <Error>0</Error>
        <Estatus>OK</Estatus>
    </EstadoRespuesta>
    <NewDataSet1>
        <Table1>
            <Cuenta>XZY07633</Cuenta>
        </Table1>
        <Table1>
            <FechadelBalance>2016-Nov-18 19:15</FechadelBalance>
        </Table1>
        <Table1>
            <Balance>60.7</Balance>
        </Table1>
        <Table1>
            <Lectura>2,152.4</Lectura>
        </Table1>
        <Table1>
            <Suspensinalllegara>2,213.1</Suspensinalllegara>
        </Table1>
        <Table1>
            <Fechaaproximadadecorte>2017-Jan-04 15:37</Fechaaproximadadecorte>
        </Table1>
    </NewDataSet1>
</xml>

Nevertheless, you have to add all non-QName chars to the second argument of the translate expression

translate(Elemento,' *ó','')

in the XSLT file.

Upvotes: 1

michael.hor257k
michael.hor257k

Reputation: 117140

Try it this way:

XSLT 1.0

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

<xsl:variable name="valid-chars">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.</xsl:variable>

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

<xsl:template match="Table1">
    <xsl:copy>
        <xsl:element name="{translate(Elemento, translate(Elemento, $valid-chars, ''), '')}">
             <xsl:value-of select="Valor"/>
        </xsl:element>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Note:

  1. You need to add characters you want to preserve (e.g. ó) to the list of valid characters.

  2. Even after filtering the invalid characters, the input may still be an invalid XML element name (for example, if it starts with a digit).

Upvotes: 1

Related Questions