Re: [xsl] XSLT 1: From flat XML to tree hierarchy XML. Can't seem to find the right way to do it.

Subject: Re: [xsl] XSLT 1: From flat XML to tree hierarchy XML. Can't seem to find the right way to do it.
From: "James A. Robinson" <jim.robinson@xxxxxxxxxxxx>
Date: Thu, 25 May 2006 09:30:05 -0700
I'm afraid I'm not following what you want done with the namespaces,
but in general I think that if you are stuck doing this in XSLT 1.0
you can achieve your goal of emitting a tree from a flat list by using
the Muenchian grouping technique:

  http://www.jenitennison.com/xslt/grouping/muenchian.html

I'm dashing this off before I head to work, so apologies if it isn't
as complete as you spec out.  I *think* it does what you want in terms
of the tree structure.  Apologies if I've misunderstood what you are
after!

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0" xmlns:abel="http://something.com";>

  <xsl:output indent="yes" />

  <!-- table-by-category lets us look up all tableName elements matching a category -->
  <xsl:key name="table-by-category" match="abel:tableName" use="@category-name" />

  <!-- 
    At the root of our output tree emit the tableName for 'Root'
  -->
  <xsl:template match="/">
    <xsl:element name="abel:tree">
      <xsl:attribute name="id">0</xsl:attribute>

      <!-- process the first tableName with a category-name matching 'Root' -->
      <xsl:apply-templates select="//abel:tableName[@category-name='Root'][1]" />
    </xsl:element>
  </xsl:template>

  <!-- 
    Process each 1st tableName by emitting an item and
    then processing its descendents and then its children.
  -->
  <xsl:template match="abel:tableName[generate-id(.)=generate-id(key('table-by-category', @category-name)[1])]">
    <xsl:element name="abel:item">

      <xsl:attribute name="text">
        <xsl:value-of select="string(.)" />
      </xsl:attribute>

      <xsl:attribute name="id">
        <xsl:choose>
          <xsl:when test="@id">
            <xsl:value-of select="@id" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@category-name" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>

      <!-- process each 1st tableName which has a parent-category-name matching our category-name -->
      <xsl:apply-templates select="//abel:tableName
                  [@category-parent-name=current()/@category-name]
                  [generate-id(.)=generate-id(key('table-by-category', @category-name)[1])]" />

      <!-- process all other tableName entries with the same category-name -->
      <xsl:apply-templates select="key('table-by-category',@category-name)[position() != 1]" />

    </xsl:element>
  </xsl:template>

  <!--
    Catch-all rule to emit an item for each tableName, not processing
    any children or siblings.
  -->
  <xsl:template match="abel:tableName">
    <xsl:element name="abel:item">

      <xsl:attribute name="text">
        <xsl:value-of select="string(.)" />
      </xsl:attribute>

      <xsl:attribute name="id">
        <xsl:choose>
          <xsl:when test="@id">
            <xsl:value-of select="@id" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@category-name" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>

    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson                       jim.robinson@xxxxxxxxxxxx
Stanford University HighWire Press      http://highwire.stanford.edu/
+1 650 7237294 (Work)                   +1 650 7259335 (Fax)

Current Thread