I'm having a hard time writing an XSLT to move all nodes having a same attribute value to the same level.
Here's an example:
<root>
<object Name="1">
<Property Name="a1" Value="a">
<Property Name="a1.1" Value="a"/>
<Property Name="a1.2" Value="a">
<Property Name="a1.2.1" Value="a"/>
<Property Name="a1.2.2" Value="a"/>
</Property>
</Property>
<Property Name="b1" Value="b"/>
</object>
</root>
Currently it is possible to nest properties with value a inside one another (there is no limit for the amount of nodes or nesting level). This model will change to only allow this type of property at the object level. Which should look like this after the transformation (the order of the elements doesn't matter):
<root>
<object Name="1">
<Property Name="a1" Value="a"/>
<Property Name="a1.1" Value="a"/>
<Property Name="a1.2" Value="a">
<Property Name="a1.2.1" Value="a"/>
<Property Name="a1.2.2" Value="a"/>
<Property Name="b1" Value="b"/>
</object>
</root>
I've tried solving this with this very similar question, the main difference being that in the example the node won't be copied, but its values will be used. I haven't been able to figure out how to copy the entire node though.
EDIT
The above example is over simplified. The properties will contain sub-elements which will have to be copied as well
<root>
<object Name="1">
<Property Name="a1" Value="a">
<x>x1</x>
<y>y1</y>
<z>z1</z>
<Property Name="a1.1" Value="a">
<x>x1.1</x>
<y>y1.1</y>
<z>z1.1</z>
</Property>
<Property Name="a1.2" Value="a">
<x>x1.2</x>
<y>y1.2</y>
<z>z1.2</z>
<Property Name="a1.2.1" Value="a">
<x>x1.2.1</x>
<y>y1.2.1</y>
<z>z1.2.1</z>
</Property>
<Property Name="a1.2.2" Value="a">
<x>x1.2.1</x>
<y>y1.2.1</y>
<z>z1.2.1</z>
</Property>
</Property>
</Property>
<Property Name="b1" Value="b"/>
</object>
</root>
Should become this after the transformation:
<root>
<object Name="1">
<Property Name="a1" Value="a">
<x>x1</x>
<y>y1</y>
<z>z1</z>
</Property>
<Property Name="a1.1" Value="a">
<x>x1.1</x>
<y>y1.1</y>
<z>z1.1</z>
</Property>
<Property Name="a1.2" Value="a">
<x>x1.2</x>
<y>y1.2</y>
<z>z1.2</z>
</Property>
<Property Name="a1.2.1" Value="a">
<x>x1.2.1</x>
<y>y1.2.1</y>
<z>z1.2.1</z>
</Property>
<Property Name="a1.2.2" Value="a">
<x>x1.2.1</x>
<y>y1.2.1</y>
<z>z1.2.1</z>
</Property>
<Property Name="b1" Value="b"/>
</object>
</root>
If you start with the XSLT identity template, all you need is just another template that matches Property that copies the element and attributes, but outputs the child elements after the element, rather that within it.
<xsl:template match="Property">
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Property">
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:template>
</xsl:stylesheet>
Note that I am assuming Property elements can only contain other Property elements as children here.
Re your edited question - try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Property">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::Property)]"/>
</xsl:copy>
<xsl:apply-templates select="Property" />
</xsl:template>
</xsl:stylesheet>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With