[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Jostein Austvik Jacobsen wrote:
The following stylesheet creates above output structure, only white space/indenting is different from what you posted:
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="headline[@level = $level]">
<xsl:choose>
<xsl:when test="self::headline[@level = $level]">
<xsl:element name="level{$level}">
<xsl:element name="h{$level}">
<xsl:value-of select="."/>
</xsl:element>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="document">
<xsl:variable name="v1">
<headline level="1"><xsl:value-of select="metaData/title"/></headline>
<xsl:copy-of select="contentSection/node()"/>
</xsl:variable>
<body>
<xsl:sequence select="mf:group($v1/node(), 1)"/>
</body>
</xsl:template>
</xsl:stylesheet>
--
Re: [xsl] Grouping by attribute
Subject: Re: [xsl] Grouping by attribute From: Martin Honnen <Martin.Honnen@xxxxxx> Date: Mon, 19 Oct 2009 15:12:56 +0200 |
Jostein Austvik Jacobsen wrote:
I've got this flat-structured XML:
<document> <metaData> <title>Title</title> <publisher>Publisher</publisher> </metaData> <contentSection> <p>text</p>
<headline level="2">Headline</headline> <p>text</p> <p>text</p>
<headline level="2">Section</headline> <p>text</p> <pagenum id="page2"/> <p>text</p> <headline level="3">Subsection</headline> <p>text</p>
<headline level="2">Section</headline> <p>text</p> <p>text</p> </contentSection> </document>
And want it transformed to this XML:
<body> <level1> <h1>Title</h1> <p>text</p>
<level2> <h2>Headline</h2> <p>text</p> <p>text</p> </level2>
<level2> <h2>Section</h2> <p>text</p> <pagenum id="page2"/> <p>text</p> <level3> <h3>Subsection</h3> <p>text</p> </level3> </level2>
<level2> <h2>Section</h2> <p>text</p> <p>text</p> </level2> </level1> </body>
How would I do that using XSLT? XSLT 2.0 solutions are ok.
The following stylesheet creates above output structure, only white space/indenting is different from what you posted:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/2009/mf" exclude-result-prefixes="xs mf">
<xsl:output indent="yes"/> <xsl:strip-space elements="*"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="headline[@level = $level]">
<xsl:choose>
<xsl:when test="self::headline[@level = $level]">
<xsl:element name="level{$level}">
<xsl:element name="h{$level}">
<xsl:value-of select="."/>
</xsl:element>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="document">
<xsl:variable name="v1">
<headline level="1"><xsl:value-of select="metaData/title"/></headline>
<xsl:copy-of select="contentSection/node()"/>
</xsl:variable>
<body>
<xsl:sequence select="mf:group($v1/node(), 1)"/>
</body>
</xsl:template>
</xsl:stylesheet>
--
Martin Honnen http://msmvps.com/blogs/martin_honnen/
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Grouping by attribute, Jostein Austvik Jaco | Thread | RE: [xsl] Grouping by attribute, Michael Kay |
[xsl] Grouping by attribute, Jostein Austvik Jaco | Date | RE: [xsl] Grouping by attribute, Michael Kay |
Month |
Keywords