Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identity transformation in XSLT

Tags:

xml

xslt

I have this source XML:

<?xml version="1.0"?>
<root>
   <item1>
      <name>test</name>
      <price>160</price>
      <stock>4</stock>
      <country>Belgium</country>
   </item1>
   <item2>
      <name>Alfa</name>

      <price>140</price>

      <stock>3</stock>

      <country>Turkey</country>
   </item2>
   <item3>
      <name>Beta</name>

      <price>110</price>

      <stock>48</stock>

      <country>Holland</country>
   </item3>
   <product id="p1">
      <name>Delta</name>

      <price>800</price>

      <stock>4</stock>

      <country>Denmark</country>
   </product>
   <product id="p2">
      <name>Golf</name>

      <price>1000</price>

      <stock>5</stock>

      <country>Germany</country>
   </product>
   <product id="p3">
      <name>Alfa</name>

      <price>1200</price>

      <stock>19</stock>

      <country>Germany</country>
   </product>
   <product id="p4">
      <name>Foxtrot</name>

      <price>1500</price>

      <stock>5</stock>

      <country>Australia</country>
   </product>
   <product id="p5">
      <name>Tango</name>

      <price>1225</price>

      <stock>3</stock>

      <country>Japan</country>
   </product>
</root>

And I want it to look like this:

<?xml version="1.0"?>
<root>
   <action>
      <name>test</name>

      <price>160</price>

      <stock>4</stock>

      <country>Belgium</country>
   </action>
   <action>
      <name>Alfa</name>

      <price>140</price>

      <stock>3</stock>

      <country>Turkey</country>
   </action>
   <action>
      <name>Beta</name>

      <price>110</price>

      <stock>48</stock>

      <country>Holland</country>
   </action>
   <action>
      <name>Delta</name>

      <price>800</price>

      <stock>4</stock>

      <country>Denmark</country>
   </action>
   <action>
      <name>Golf</name>

      <price>1000</price>

      <stock>5</stock>

      <country>Germany</country>
   </action>
   <action>
      <name>Alfa</name>

      <price>1200</price>

      <stock>19</stock>

      <country>Germany</country>
   </action>
   <action>
      <name>Foxtrot</name>

      <price>1500</price>

      <stock>5</stock>

      <country>Australia</country>
   </action>
   <action>
      <name>Tango</name>

      <price>1225</price>

      <stock>3</stock>

      <country>Japan</country>
   </action>
</root>

So the <item1> to <item3> turn into

<action>

And the <product> loses its attribute, and also turns into

<action>

Can somebody show me how to do this with XSLT? Because I have 2 different XSL's now. And I want to combine them to create just one XSL.

Thanks in advance

like image 315
Dennis van den Brom Avatar asked Dec 03 '22 05:12

Dennis van den Brom


2 Answers

This transformation:

<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="product|*[starts-with(name(), 'item')]">
  <action>
   <xsl:apply-templates select="node()|@*"/>
  </action>
 </xsl:template>

 <xsl:template match="product/@id"/>
</xsl:stylesheet>

when applied on the provided XML document:

<root>
    <item1>
        <name>test</name>
        <price>160</price>
        <stock>4</stock>
        <country>Belgium</country>
    </item1>
    <item2>
        <name>Alfa</name>
        <price>140</price>
        <stock>3</stock>
        <country>Turkey</country>
    </item2>
    <item3>
        <name>Beta</name>
        <price>110</price>
        <stock>48</stock>
        <country>Holland</country>
    </item3>
    <product id="p1">
        <name>Delta</name>
        <price>800</price>
        <stock>4</stock>
        <country>Denmark</country>
    </product>
    <product id="p2">
        <name>Golf</name>
        <price>1000</price>
        <stock>5</stock>
        <country>Germany</country>
    </product>
    <product id="p3">
        <name>Alfa</name>
        <price>1200</price>
        <stock>19</stock>
        <country>Germany</country>
    </product>
    <product id="p4">
        <name>Foxtrot</name>
        <price>1500</price>
        <stock>5</stock>
        <country>Australia</country>
    </product>
    <product id="p5">
        <name>Tango</name>
        <price>1225</price>
        <stock>3</stock>
        <country>Japan</country>
    </product>
</root>

produces the wanted, correct result:

<root>
   <action>
      <name>test</name>
      <price>160</price>
      <stock>4</stock>
      <country>Belgium</country>
   </action>
   <action>
      <name>Alfa</name>
      <price>140</price>
      <stock>3</stock>
      <country>Turkey</country>
   </action>
   <action>
      <name>Beta</name>
      <price>110</price>
      <stock>48</stock>
      <country>Holland</country>
   </action>
   <action>
      <name>Delta</name>
      <price>800</price>
      <stock>4</stock>
      <country>Denmark</country>
   </action>
   <action>
      <name>Golf</name>
      <price>1000</price>
      <stock>5</stock>
      <country>Germany</country>
   </action>
   <action>
      <name>Alfa</name>
      <price>1200</price>
      <stock>19</stock>
      <country>Germany</country>
   </action>
   <action>
      <name>Foxtrot</name>
      <price>1500</price>
      <stock>5</stock>
      <country>Australia</country>
   </action>
   <action>
      <name>Tango</name>
      <price>1225</price>
      <stock>3</stock>
      <country>Japan</country>
   </action>
</root>

Explanation:

  1. The identity rule copies every node "as-is".

  2. We have two templates overriding the identity rule. The first template matches any product or any element whose name starts with the string item. It effectively "renames" the matched element to action by creating and outputting an action element.

  3. The second overriding template matches any id attribute of any product element. This template has no body, which effectively "deletes" the matched attribute -- it is not copied/recreated in the output.

like image 71
Dimitre Novatchev Avatar answered Dec 16 '22 03:12

Dimitre Novatchev


Sounds easy:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

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

  <xsl:template match="root/*">
    <action>
      <xsl:apply-templates/>
    </action>
  </xsl:template>

</xsl:stylesheet>

If you want us to combine your existing code you need to post it.

like image 34
Martin Honnen Avatar answered Dec 16 '22 02:12

Martin Honnen