I've been given the follow XML (produced by someone from an Excel spreadsheet)
<Records>
<record>
<Domain>Domain 1</Domain>
<Section>Section A</Section>
<label>Option X 1</label>
<Keyword>Unique KW 1</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
<record>
<Domain>Domain 1</Domain>
<Section>Section B</Section>
<label>Option X 2</label>
<Keyword>Unique KW 2</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
<record>
<Domain>Domain 2</Domain>
<Section>Section A</Section>
<label>Option X 3</label>
<Keyword>Unique KW 3</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
<record>
<Domain>Domain 1</Domain>
<Section>Section A</Section>
<label>Option X 4</label>
<Keyword>Unique KW 4</Keyword>
<Control>Checkbox</Control>
<Default>FALSE</Default>
</record>
<record>
<Domain>Domain 1</Domain>
<Section>Section B</Section>
<label>Option X 5</label>
<Keyword>Unique KW 5</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
<record>
<Domain>Domain 2</Domain>
<Section>Section B</Section>
<label>Option X 6</label>
<Keyword>Unique KW 6</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
<record>
<Domain>Domain 1</Domain>
<Section>Section A</Section>
<label>Option X 7</label>
<Keyword>Unique KW 7</Keyword>
<Control>Checkbox</Control>
<Default>TRUE</Default>
</record>
</Records>
And I've been asked to transform it into the following using XSLT 1.0
<Configuration>
<Domain name="Domain 1">
<Section name="Section A">
<Option keyword="Unique KW 1" name="Option X 1">
<Control type="Checkbox" default="True" />
</Option>
<Option keyword="Unique KW 3" name="Option X 3">
<Control type="Checkbox" default="True" />
</Option>
<Option keyword="Unique KW 7" name="Option X 7">
<Control type="Checkbox" default="True" />
</Option>
</Section>
<Section name="Section B">
<Option keyword="Unique KW 2" name="Option X 2">
<Control type="Checkbox" default="True" />
</Option>
<Option keyword="Unique KW 5" name="Option X 5">
<Control type="Checkbox" default="True" />
</Option>
</Section>
</Domain>
<Domain name="Domain 2">
<Section name="Section A">
<Option keyword="Unique KW 3" name="Option X 3">
<Control type="Checkbox" default="True" />
</Option>
</Section>
<Section name="Section B">
<Option keyword="Unique KW 6" name="Option X 6">
<Control type="Checkbox" default="True" />
</Option>
</Section>
</Domain>
</Configuration>
I've used XSLT in a limited capacity in the past but I'm struggling getting a single element out (eg Domain and Section), the output I get is one per element in the source where I need 1 per value in the source (if that makes sense). I just seem to get lots of
Domain instead of just two (Domain 1 and Domain 2), same with the Section
Is there any way of doing this with XSLT 1.0 or am I just wasting my time?
(Also, the data I've given is an example, edited to remove sensitive data and size, there are far more Domains and Section etc)
(The little I've got so far)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:dt="urn:schemas-microsoft-com:datatypes">
<xsl:output media-type="xml" indent="yes" />
<xsl:template match="/Records">
<Configuration>
<xsl:for-each select="record/Domain">
<Domain name="{text()}">
<Section name="{../Section/text()}">
<Option keyword="{../Keyword/text()}">
<Control type="{../Control/text()}"/>
</Option>
</Section>
</Domain>
</xsl:for-each>
</Configuration>
</xsl:template>
</xsl:stylesheet>
EDIT: After looking at Michaels link (thanks) I'm getting closer. The outer group (Domain) is working but the inner group isn't
<xsl:key name="domain-name" match="record" use="Domain" />
<xsl:key name="section-name" match="record" use="Section" />
<xsl:template match="/Records">
<Configuration>
<xsl:for-each select="record[count(. | key('domain-name', Domain)[1]) = 1]">
<xsl:sort select="Domain" />
<Domain name="{Domain}">
<xsl:for-each select="record[count(. | key('section-name', Section)[1]) = 1]">
<xsl:sort select="Section" />
<Section name="{Section}">
<Option keyword="{Keyword/text()}">
<Control type="{Control/text()}"/>
</Option>
</Section>
</xsl:for-each>
</Domain>
</xsl:for-each>
</Configuration>
</xsl:template>
Is giving me
<Configuration>
<Domain name="Domain 1" />
<Domain name="Domain 2" />
</Configuration>