tags:

views:

41

answers:

1

Hi, I have a custom XML that I need to transform to another XML format, using XSL.

Input:

<Feed>
  <repository>
  <item-descriptor name="product">
  <property name="id">123</property>
  <property name="display">asdf</property>
  <property name="attr1">attr1</property>
  <property name="attr2">attr2</property>
  </item-descriptor>
  </repository>
</Feed>

Output:

<Feed>
  <Products>
  <product>
  <id>123</id>
  <display>asdf</display>
  <attr1>attr1</attr>
  <attr2>attr2</attr2>
  </product>
  </Products>
</Feed>

Following XSL is used to get the desired output.

XSL:

<xsl:template match="/">
  <xsl:apply-templates select="Feed"/>
  </xsl:template>
  <xsl:template match="Feed">
  <Feed>
  <Products>
  <xsl:apply-templates select="repository/item-descriptor[@name='product']"/>
  </Products>
  </Feed>
  </xsl:template>
  <xsl:template match="repository/item-descriptor[@name='product']">
  <product>
   <xsl:apply-templates select="property"/>
  </product>
  </xsl:template>
  <xsl:template match="property">
  <xsl:if test=@name='id'>
  <id><xsl:value-of select='.'></id>
  </xsl:if>  <xsl:if test=@name='display'>
  <display><xls:value-of select='.'></display>
  <xsl:if test=@name='attr1'>
  <attr1><xsl:value-of select='.'></attr1>
 </xsl:if>
  <xsl:if test=@name='attr2'>
 <attr2><xls:value-of select='.'></attr2>
</xsl:template>

Now I need to generate the following output, please help me out in modifying the above XSL to get the output below:

<Feed>
  <Products>
  <product>
  <id>123</id>
  <display>asdf</display>
  <attributes>
  <aatr1>attr1</attr1>
  <attr2>attr2</attr2>
  </attributes>
  </product>
  </Products>
</Feed>
+2  A: 

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="*[item-descriptor/@name='product']">
  <Products>
   <xsl:apply-templates/>
  </Products>
 </xsl:template>

 <xsl:template match="item-descriptor[@name='product']">
  <product>
      <xsl:apply-templates select="*/@name[not(starts-with(.,'attr'))]"/>
      <attributes>
        <xsl:apply-templates select="*/@name[starts-with(.,'attr')]"/>
      </attributes>
  </product>
 </xsl:template>

 <xsl:template match="@name">
  <xsl:element name="{.}">
    <xsl:apply-templates select="../node()"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML file:

<Feed>
    <repository>
        <item-descriptor name="product">
            <property name="id">123</property>
            <property name="display">asdf</property>
            <property name="attr1">attr1</property>
            <property name="attr2">attr2</property>
        </item-descriptor>
    </repository>
</Feed>

produces the wanted, correct result:

<Feed>
    <Products>
        <product>
            <id>123</id>
            <display>asdf</display>
            <attributes>
                <attr1>attr1</attr1>
                <attr2>attr2</attr2>
            </attributes>
        </product>
    </Products>
</Feed>
Dimitre Novatchev
@Dimitre: +1 Good answer!
Alejandro