<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Traveller>001</Traveller>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Traveller>001</Traveller>
</Transport>
</Products>
</Sections>
<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Traveller>002</Traveller>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Traveller>002</Traveller>
</Transport>
</Products>
</Sections>
I have a specific problem with the ordering of some XML. From the above example I need to change the format so that I select distinct only on the TransportSequence. I then need to assign any 'Traveller' nodes as children to produce something like this:
<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Travellers>
<Traveller>001</Traveller>
<Traveller>002</Traveller>
</Travellers>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Travellers>
<Traveller>001</Traveller>
<Traveller>002</Traveller>
</Travellers>
</Transport>
</Products>
</Sections>
The other problem is that in the Transport node also contains lots of children and grandchildren nodes not shown in this example. There can also be many travllers belonging to a TravellerSequence. There are also many TransportSequence numbers.
Here is an XSLT 2.0 stylesheet to be run with XSLT 2.0 processors like Saxon 9 or AltovaXML:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[Sections]">
<xsl:copy>
<Sections>
<Products>
<xsl:for-each-group select="Sections/Products/Transport" group-by="TransportSequence">
<Transport>
<TransportSequence><xsl:value-of select="current-grouping-key()"/></TransportSequence>
<Travellers>
<xsl:copy-of select="current-group()/Traveller"/>
</Travellers>
</Transport>
</xsl:for-each-group>
</Products>
</Sections>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
It transforms
<Root>
<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Traveller>001</Traveller>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Traveller>001</Traveller>
</Transport>
</Products>
</Sections>
<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Traveller>002</Traveller>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Traveller>002</Traveller>
</Transport>
</Products>
</Sections>
</Root>
into
<Root>
<Sections>
<Products>
<Transport>
<TransportSequence>1</TransportSequence>
<Travellers>
<Traveller>001</Traveller>
<Traveller>002</Traveller>
</Travellers>
</Transport>
<Transport>
<TransportSequence>2</TransportSequence>
<Travellers>
<Traveller>001</Traveller>
<Traveller>002</Traveller>
</Travellers>
</Transport>
</Products>
</Sections>
</Root>
[edit] To complete the answer, if you want to use an XSLT 1.0 processor, a solution using Muenchian grouping looks as follows:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="by-seq" match="Sections/Products/Transport" use="TransportSequence"/>
<xsl:template match="*[Sections]">
<xsl:copy>
<Sections>
<Products>
<xsl:for-each select="Sections/Products/Transport[generate-id() = generate-id(key('by-seq', TransportSequence)[1])]">
<Transport>
<xsl:copy-of select="TransportSequence"/>
<Travellers>
<xsl:copy-of select="key('by-seq', TransportSequence)/Traveller"/>
</Travellers>
</Transport>
</xsl:for-each>
</Products>
</Sections>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>