Link to home
Start Free TrialLog in
Avatar of Letterpart
LetterpartFlag for United Kingdom of Great Britain and Northern Ireland

asked on

adding structure to flat-ish XML file via XSLT

I have some data that, when simplified, looks like this:


<data>
	<section>A..</section>
	<section type="1">B..</section>
	<section>C..</section>
	<section>D..</section>
	<section type="1">E..</section>
	<section>F..</section>
	<section>G..</section>
	<section>H..</section>
	<nonsection>J..</nonsection>
	<nonsection>K..</nonsection>
</data>

Open in new window


A type="1" attribute on the section element indicates the start of a group that ends when either another type="1" is found, or when a nonsection element is found.

I thought that putting some structure into the XML would help me with some work I need to do at the group level.
And so I would like to be able to transform the above to this:

<data>
	<section>A..</section>
	<sectiongroup>
		<section type="1">B..</section>
		<section>C..</section>
		<section>D..</section>
	</sectiongroup>
	<sectiongroup>
		<section type="1">E..</section>
		<section>F..</section>
		<section>G..</section>
		<section>H..</section>
	</sectiongroup>		
	<nonsection>J..</nonsection>
	<nonsection>K..</nonsection>
</data>

Open in new window


And that would then enable me to 'do something' in sectiongroup.

Can anyone help with the XSLT that would transform the data to add in sectiongroup elements?
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well, not that bad actrually,
but a bit of recursive processing on the following axis,
kind of hard to grasp

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    
    <xsl:output indent="yes"></xsl:output>
    
    <xsl:template match="data">
        <data>
            <xsl:apply-templates select="*[1]" mode="start-group"/>
        </data>
     </xsl:template>
    
    <xsl:template match="section[@type = '1']" mode="start-group">
        <sectiongroup>
            <xsl:copy-of select="."/>
            <xsl:apply-templates select="following-sibling::*[1]" mode="in-group"/>
        </sectiongroup>
        <xsl:apply-templates select="following-sibling::*[@type = 1 or name() = 'nonsection'][1]" mode="start-group"/>
    </xsl:template>
    
    <xsl:template match="section[not(@type = '1')] | nonsection " mode="start-group">
        <xsl:copy-of select="."/>
        <xsl:apply-templates select="following-sibling::*[1]" mode="start-group"/>
    </xsl:template>
    
    <xsl:template match="section[not(@type = '1')]" mode="in-group">
        <xsl:copy-of select="."/>
        <xsl:apply-templates select="following-sibling::*[1]" mode="in-group"/>
    </xsl:template>
    
    <xsl:template match="section[@type = '1'] | nonsection " mode="in-group"/>
    
    
</xsl:stylesheet>

Open in new window

Avatar of Letterpart

ASKER

Excellent, thanks Geert.
The XSLT2 solution should be fine for me - but very interesting to compare them.
Thanks.