Assume I have this XML
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Level1>
<Level1Val level1="Animal" />
<Level1Val level1="Vegetable" />
<Level1Val level1="Mineral" />
</Level1>
<Level3>
<Level3Val level1="Animal" level2="Cat" level3="Puma"/>
<Level3Val level1="Animal" level2="Cat" level3="Tiger"/>
<Level3Val level1="Animal" level2="Cat" level3="Lion"/>
<Level3Val level1="Animal" level2="Bear" level3="Black Bear"/>
<Level3Val level1="Animal" level2="Bear" level3="Brown Bear"/>
<Level3Val level1="Animal" level2="Bear" level3="Panda Bear"/>
<Level3Val level1="Vegetable" level2="Fruit" level3="Apple"/>
<Level3Val level1="Vegetable" level2="Fruit" level3="Peach"/>
<Level3Val level1="Vegetable" level2="Fruit" level3="Banana"/>
<Level3Val level1="Vegetable" level2="Green" level3="Celery"/>
<Level3Val level1="Vegetable" level2="Green" level3="Broccoli"/>
<Level3Val level1="Vegetable" level2="Green" level3="Kale"/>
<Level3Val level1="Mineral" level2="Liquid" level3="Oil"/>
<Level3Val level1="Mineral" level2="Liquid" level3="Kerosene"/>
<Level3Val level1="Mineral" level2="Liquid" level3="Diesel"/>
<Level3Val level1="Mineral" level2="Solid" level3="Quartz"/>
<Level3Val level1="Mineral" level2="Solid" level3="Feldspar"/>
<Level3Val level1="Mineral" level2="Solid" level3="Garnet"/>
</Level3>
</Root>
And I want to display the results in a three-level hierarchy. The following XSLT pattern is what I used.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:key name="Level1PlusLevel2" match="/Root/Level3/Level3Val" use="concat(@level1,'+',level2)" />
<xsl:key name="Level2Type" match="Level3/Level3Val" use="@level2"/>
<xsl:variable name="Level1Vals" select="/Root/Level1/Level1Val" />
<xsl:variable name="Level2Vals" select="Root/Level3/Level3Val[generate-id()=generate-id(key('Level2Type', @level2)[1])]" />
<xsl:template match="/Root">
<html>
<xsl:apply-templates select="$Level1Vals" />
</html>
</xsl:template>
<xsl:template match="Level1Val">
<!-- output info about Level 1 -->
<div class="level1">
<p>level 1: <xsl:value-of select="@level1" /></p>
<xsl:apply-templates select="$Level2Vals" mode="Level2">
<xsl:with-param name="level1_id" select="@level1"/>
</xsl:apply-templates>
</div>
</xsl:template>
<xsl:template match="Level3Val" mode="Level2">
<xsl:param name="level1_id" />
<!-- output info about Level 2 -->
<div class="level2">
<p>level 2: <xsl:value-of select="@level2" /></p>
<xsl:apply-templates select="key('Level1PlusLevel2',concat($level1_id,'+',@level2))" />
</div>
</xsl:template>
<xsl:template match="Level3Val">
<!-- output info about Level 3 -->
<div class="level3">
<p>level 3: <xsl:value-of select="@level3" /></p>
</div>
</xsl:template>
</xsl:stylesheet>
Note that a more common XML input would probably have a single table of Level2 elements. But in the case I just coded for, there was a separate list of Level1 elements.
I did this sort of from memory and there may be errors. If you see an obvious error please do point it out to me.
No comments:
Post a Comment