Reputation: 5
That's my very first question according to XSLT. I would like to transform a XML structure by using XSLT.
The relevant part of my XML source:
<field tag="ElementName">
<subfield code="S">p</subfield>
<subfield code="a">Content 1 for S=P</subfield>
</field>
<field tag="ElementName">
<subfield code="S">p</subfield>
<subfield code="a">Content 2 for S=P</subfield>
</field>
<field tag="ElementName">
<subfield code="S">p</subfield>
<subfield code="a">Content 3 for S=P</subfield>
</field>
<field tag="ElementName">
<subfield code="S">g</subfield>
<subfield code="a">Content 1 for S=G</subfield>
</field>
<field tag="ElementName">
<subfield code="S">g</subfield>
<subfield code="a">Content 2 for S=G</subfield>
</field>
<field tag="ElementName">
<subfield code="S">s</subfield>
<subfield code="a">Content 1 for S=S</subfield>
</field>
<field tag="ElementName">
<subfield code="S">s</subfield>
<subfield code="a">Content 2 for S=S</subfield>
</field>
<field tag="ElementName">
<subfield code="S">s</subfield>
<subfield code="a">Content 3 for S=S</subfield>
</field>
<field tag="ElementName">
<subfield code="S">s</subfield>
<subfield code="a">Content 4 for S=S</subfield>
</field>
Next what I would like the XML to look like after transformation:
<field tag="ElementName_P">
<subfield code="a">Content 1 for S=P</subfield>
<subfield code="a">Content 2 for S=P</subfield>
<subfield code="a">Content 3 for S=P</subfield>
</field>
<field tag="ElementName_G">
<subfield code="a">Content 1 for S=G</subfield>
<subfield code="a">Content 2 for S=G</subfield>
</field>
<field tag="ElementName_S">
<subfield code="a">Content 1 for S=S</subfield>
<subfield code="a">Content 2 for S=S</subfield>
<subfield code="a">Content 3 for S=S</subfield>
<subfield code="a">Content 4 for S=S</subfield>
</field>
I know how to get the attribute values and the field values using xsl:variable and xsl:value-of. What I would like to know is how to group the contents from the subfields with code="a". Have been trying for hours. Are there any possibilities using XPath?
Thx for support!
Upvotes: 0
Views: 432
Reputation: 11416
As example how this can be done in XSLT 1.0:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" encoding="utf-8" method="xml"
omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="sCode" match="subfield[@code='S']" use="." />
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:template match="field">
<xsl:for-each select="subfield[generate-id() =
generate-id(key('sCode', .)[1])]">
<xsl:variable name="elements" select="key('sCode', .)" />
<field>
<xsl:attribute name="tag" select="concat('ElementName_',
translate($elements, $smallcase, $uppercase))"/>
<xsl:apply-templates select="//subfield[(./text() = $elements)]"
mode="sorted"/>
</field>
</xsl:for-each>
</xsl:template>
<xsl:template match="subfield" mode="sorted">
<xsl:copy>
<xsl:attribute name="code" select="."/>
<xsl:value-of select="./following-sibling::subfield[@code='a']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when applied to your input XML has the ouput
<field tag="ElementName_P">
<subfield code="p">Content 1 for S=P</subfield>
<subfield code="p">Content 2 for S=P</subfield>
<subfield code="p">Content 3 for S=P</subfield>
</field>
<field tag="ElementName_G">
<subfield code="g">Content 1 for S=G</subfield>
<subfield code="g">Content 2 for S=G</subfield>
</field>
<field tag="ElementName_S">
<subfield code="s">Content 1 for S=S</subfield>
<subfield code="s">Content 2 for S=S</subfield>
<subfield code="s">Content 3 for S=S</subfield>
<subfield code="s">Content 4 for S=S</subfield>
</field>
In case you're using XSLT 2.0 it wouldn't be necessary to translate the code value for the ElementName
tag in the output but you could just use the function uppercase()
.
As references for XSLT grouping you can have a look at e.g. http://www.jenitennison.com/xslt/grouping/muenchian.xml and http://www.dpawson.co.uk/xsl/sect2/N4486.html
Upvotes: 0