user1827371
user1827371

Reputation: 39

Rename OR Merge Duplicate XML tag with XSL

I have following XML file which has duplicate DateSold tag in each SALES tag. I need those to be replaced as DateSold and TimeSold. Or merge the date and time part as a single tag.

Source XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <SALES>
      <InvoiceID>A13A30000011</InvoiceID>
      <LineID>1</LineID>
      <UPC>058030020130</UPC>
      <Desc>PS WQ VIT E 200IU 100'S</Desc>
      <DateSold>2013-10-30</DateSold>
      <DateSold>10:02:42</DateSold>
      <QTY>000001</QTY>
      <UnitRetail>000006.99</UnitRetail>
      <UnitCost>000003.37</UnitCost>
   </SALES>
   <SALES>
      <InvoiceID>A13A30000021</InvoiceID>
      <LineID>2</LineID>
      <UPC>063601699165</UPC>
      <Desc>GENTEAL GEL DROPS 15ML</Desc>
      <DateSold>2013-10-30</DateSold>
      <DateSold>10:03:15</DateSold>
      <QTY>000001</QTY>
      <UnitRetail>000010.99</UnitRetail>
      <UnitCost>000007.44</UnitCost>
   </SALES>
</root>

the Output would be:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <SALES>
      <InvoiceID>A13A30000011</InvoiceID>
      <LineID>1</LineID>
      <UPC>058030020130</UPC>
      <Desc>PS WQ VIT E 200IU 100'S</Desc>
      <DateSold>2013-10-30</DateSold>
      <TimeSold>10:02:42</TimeSold>
      <QTY>000001</QTY>
      <UnitRetail>000006.99</UnitRetail>
      <UnitCost>000003.37</UnitCost>
   </SALES>
   <SALES>
      <InvoiceID>A13A30000021</InvoiceID>
      <LineID>2</LineID>
      <UPC>063601699165</UPC>
      <Desc>GENTEAL GEL DROPS 15ML</Desc>
      <DateSold>2013-10-30</DateSold>
      <TimeSold>10:03:15</TimeSold>
      <QTY>000001</QTY>
      <UnitRetail>000010.99</UnitRetail>
      <UnitCost>000007.44</UnitCost>
   </SALES>
</root>

It is OK if it be merged as

    <SALES>
    <InvoiceID>A13A30000021</InvoiceID>
    <LineID>2</LineID>
    <UPC>063601699165</UPC>
    <Desc>GENTEAL GEL DROPS 15ML</Desc>
    <DateSold>2013-10-30 10:03:15</TimeSold>
    <QTY>000001</QTY>
    <UnitRetail>000010.99</UnitRetail>
    <UnitCost>000007.44</UnitCost>      
</SALES>

Upvotes: 1

Views: 92

Answers (2)

user1827371
user1827371

Reputation: 39

I found a solution finally. The following xslt replaces the second Datesold tag as TimeSold in each Sales tag.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>
<xsl:template match="SALES/DateSold[2]">
    <TimeSold>
        <xsl:apply-templates select="@*|node()" />
    </TimeSold>
</xsl:template>
</xsl:stylesheet>

I got the final result as:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <SALES>
    <InvoiceID>A13A30000011</InvoiceID>
    <LineID>1</LineID>
    <UPC>058030020130</UPC>
    <Desc>PS WQ VIT E 200IU 100'S</Desc>
    <DateSold>2013-10-30</DateSold>
    <TimeSold>10:02:42</TimeSold>
    <QTY>000001</QTY>
    <UnitRetail>000006.99</UnitRetail>
    <UnitCost>000003.37</UnitCost>
  </SALES>
  <SALES>
    <InvoiceID>A13A30000021</InvoiceID>
    <LineID>2</LineID>
    <UPC>063601699165</UPC>
    <Desc>GENTEAL GEL DROPS 15ML</Desc>
    <DateSold>2013-10-30</DateSold>
    <TimeSold>10:03:15</TimeSold>
    <QTY>000001</QTY>
    <UnitRetail>000010.99</UnitRetail>
    <UnitCost>000007.44</UnitCost>
  </SALES>
</root>

Upvotes: 1

Matthias
Matthias

Reputation: 3592

Well you do not show what you have tried so far, so I will only give some more general advise.

As always, if you want to keep most of the structure intact, start with the identity template to copy all input to your output structure:

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

Then make some special template that treats the tag you want to handle differently. There is a big number of possible solutions for your problem, one of them would be to match the DateSold element and either write it as DateSold or TimeSold depending on whether it is the 1st or 2nd subelement in your sales element (if they are always ordered in that way).

An alternative would be to match the Sales element, select the two subelements and combine / write them differently to the output file and copy over the other elements with an apply-templates call (which then invokes your identity template again).

On how to do that specifically, show what you have tried or read up on XSLT. There is plenty resources available on the net. A good starting point might be www.w3schools.com.

They have examples for every xslt tag. The one for apply-templates is this.

Upvotes: 0

Related Questions