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.
The fn:distinct-values function returns a sequence of unique atomic values from $arg . Values are compared based on their typed value. Values of different numeric types may be equal, for example the xs:integer value 1 is equal to the xs:decimal value 1.0, so the function only returns one of these values.
Specifies the format pattern. Here are some of the characters used in the formatting pattern: 0 (Digit)
contains() Function — Determines if the first argument string contains the second.
The <xsl:attribute> element creates an attribute in the output document, using any values that can be accessed from the stylesheet. The element must be defined before any other output document element inside the output document element for which it establishes attribute values.
XSLT Soln:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With