Showing posts with label XML. Show all posts
Showing posts with label XML. Show all posts

Saturday, November 16, 2013

Two-level hierarchy in XSLT

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.

Wednesday, November 13, 2013

Been digging Philip Fearon's work today

I have been watching the videos on his YouTube channel at http://www.youtube.com/user/pgfearo.
And have been reading his blog at http://sketchpath.blogspot.com/.
Phil Fearon is doing work in XML and XSLT using some great tools he has developed including:
The specific videos I was watching were those demonstrating the power of Saxon-CE (http://www.saxonica.com/ce/index.xml )

Browser-side XSLT 2.0 with Saxon-CE is definitely something that I will be exploring and evaluating and blogging about in the near future. I also plan to leverage the various tools that Phil has developed.