tags:

views:

580

answers:

3

Please help, I’m an XSLT newbie and I’m trying to transform one XML format into another.

I need to extract unique attribute values and transform the values into a new format. The example XML below shows the original and new/target format.

I've spent ages trying to do this without any enjoy. Can anyone help out or give me some pointers?

Original format:

<base>
  <level>
    <level2 Name ="AA" value="1"/>
  </level>
  <level>
    <level2 Name ="BB" value="2"/>
  </level>
  <level>
    <level2 Name ="BB" value="3"/>
  </level>
  <level>
    <level2 Name ="CC" value="4"/>
  </level>
  <level>
    <level2 Name ="AA" value="5"/>
  </level>
</base>

New format:

<base>
  <levelNames>
    <level level2Name ="AA"/>
    <level level2Name ="BB"/>
    <level level2Name ="CC"/>
  </levelNames>
</base>

Thanks a lot.

+1  A: 

Once again the Muenchian grouping technique appears to be the missing piece.

Fairly trivial problem for it, so I'll let you do your own work to get to grips with Muench.

annakata
I'm ambivalent between voting this up and moving on and posting a solution and feeling guilty about it. Damn you. :-D But you are probably right in suspecting that this is homework, so I refrain.
Tomalak
If you've done it once, you'll see how easy it really is. You just have to get the idea. For most common XSLT problems I really recommend to first have a look here: http://www.dpawson.co.uk/xsl/sect2/sect21.html
Boldewyn
<maniacal>my plan worked!</maniacal>
annakata
@Boldewyn - yeah that's an excellent resource for beginners, albeit unsightly :)
annakata
*sigh* anyone care to explain the downvote? Is it because I didn't do the OP's work for him?
annakata
A: 

Hi,

Please create first xsl:key then u can use below code easily.

xsl:key name="LavelName" match="level2" use="@Name"

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

<xsl:template match="base">
    <xsl:element name="{local-name(.)}">
        <xsl:element name="levelNames">
           <xsl:apply-templates/>
        </xsl:element>
    </xsl:element>
</xsl:template>

    <xsl:template match="level">
        <xsl:for-each select="level2[count(.|key('LavelName', @Name)[1]) = 1]">
            <xsl:sort order="ascending" data-type="text" select="@Name"/>
            <xsl:element name="{local-name(..)}">
                <xsl:attribute name="level2Name">
                    <xsl:value-of select="@Name"/>
                </xsl:attribute>
            </xsl:element>
        </xsl:for-each>
    </xsl:template>
A: 

XSLT Soln:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="LevelDistint" match="level2" use="@Name"/>
    <xsl:template match="base">
     <base>
      <levelNames>
       <xsl:for-each select="level/level2[generate-id() = generate-id(key('LevelDistint', @Name)[1])]">
        <level>
         <xsl:attribute name="level2Name"><xsl:value-of select="normalize-space(@Name)"/></xsl:attribute>
        </level>
       </xsl:for-each>
      </levelNames>
     </base>
    </xsl:template>
</xsl:stylesheet>

XSLT O/P:

<?xml version="1.0" encoding="UTF-8"?>
<base>
    <levelNames>
     <level level2Name="AA"/>
     <level level2Name="BB"/>
     <level level2Name="CC"/>
    </levelNames>
</base>
Rashmi Pandit