Reputation: 990
I'm using an XSL file to transform some nested XML. I'd like to flatten the two-tier nested hierarchy into two lists of objects, while preserving the relationships by adding keys.
I've got the XSL set up to assign each parent's key to its children, and then output just the child notes.
The source XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<parent>
<parent-id>1</parent-id>
<child>
<child-id>child_a</child-id>
</child>
</parent>
<parent>
<parent-id>2</parent-id>
<child>
<child-id>child_b</child-id>
</child>
</parent>
</root>
The XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="text()" />
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="child">
<xsl:copy>
<xsl:copy-of select="*"/>
<foreignkey><xsl:value-of select="ancestor::parent/parent-id"/></foreignkey>
</xsl:copy>
</xsl:template>
<xsl:template match="parent">
<xsl:copy>
<xsl:copy-of select="*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
That looks like exactly what I want, but I'd also like to add the parents (now without the nested children) like this:
<parent>
<parent-id>1</parent-id>
</parent>
<parent>
<parent-id>2</parent-id>
</parent>
What do I need to add to the XSL file to get the parents to output before or after the children? I can output one or the other, but not both.
Upvotes: 0
Views: 76
Reputation: 167696
You can use apply-templates
twice inside of the root
template:
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="parent"/>
<xsl:apply-templates select="parent/child"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child">
<xsl:copy>
<xsl:copy-of select="*"/>
<foreignkey><xsl:value-of select="ancestor::parent/parent-id"/></foreignkey>
</xsl:copy>
</xsl:template>
<xsl:template match="parent">
<xsl:copy>
<xsl:copy-of select="parent-id"/>
</xsl:copy>
</xsl:template>
then you get e.g.
<root>
<parent>
<parent-id>1</parent-id>
</parent>
<parent>
<parent-id>2</parent-id>
</parent>
<child>
<child-id>child_a</child-id>
<foreignkey>1</foreignkey>
</child>
<child>
<child-id>child_b</child-id>
<foreignkey>2</foreignkey>
</child>
</root>
Upvotes: 1