Thursday, 3 December 2015

XML : XSLT 1.0 - Running a template on the result of another template

I wonder how it is done by XSLT 1.0 a transformation that passes the result of one template as an input for another within a single .xslt file:

Raw XML Input > call-template(1) > re-formatted XML > call-template(2) on the re-formatted XML

Case:

I want to write a template to re-arrange an xml so that the attributes become elements; and then run another template on the resulting xml of the first one to remove the duplicates. I can have two xsl files and pass the result of the first transformation to the second. However, I want to do it in one xslt.

The raw input xml is as follows:

  <?xml version="1.0" encoding="UTF-8"?>  <resources>      <resource>          <properties>              <property name="name" value="Foo"/>              <property name="service" value="Bar"/>              <property name="version" value="1"/>          </properties>      </resource>      <resource>          <properties>              <property name="name" value="Foo"/>              <property name="service" value="Bar"/>              <property name="version" value="2"/>          </properties>      </resource>      <resource>          <properties>              <property name="name" value="AnotherFoo"/>              <property name="service" value="AnotherBar"/>              <property name="version" value="1"/>          </properties>a      </resource>  </resources>    

When I apply the following xslt:

  <?xml version="1.0" encoding="utf-8"?>  <xsl:stylesheet version="1.0"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"      exclude-result-prefixes="msxsl">        <xsl:output method="xml" indent="yes" />        <xsl:template name="attributes-to-elements" match="/resources">          <xsl:call-template name="get-resources" />      </xsl:template>        <xsl:template name="get-resources">          <xsl:text>&#xa;</xsl:text>          <products>              <xsl:for-each select="resource">                  <xsl:call-template name="convert-attributes-to-elements" />              </xsl:for-each>          </products>      </xsl:template>        <xsl:template name="convert-attributes-to-elements">          <product>              <name>                  <xsl:value-of select="properties/property[@name='name']/@value" />              </name>              <service>                  <xsl:value-of select="properties/property[@name='service']/@value" />              </service>          </product>      </xsl:template>  </xsl:stylesheet>    

I am able to re-format the xml without the versions and get the output which does not contain versions and the attributes has become elements:

  <?xml version="1.0" encoding="UTF-8"?>  <products>      <product>          <name>Foo</name>          <service>Bar</service>      </product>      <product>          <name>Foo</name>          <service>Bar</service>      </product>      <product>          <name>AnotherFoo</name>          <service>AnotherBar</service>      </product>  </products>    

Now, the thing I want is to pass this modified xml to some template as the input xml and remove the duplicates. Finally, I want to get an xml like:

  <?xml version="1.0" encoding="UTF-8"?>  <products>      <product>          <name>Foo</name>          <service>Bar</service>      </product>      <product>          <name>AnotherFoo</name>          <service>AnotherBar</service>      </product>  </products>    

No comments:

Post a Comment