Re: Flattening a tree

Subject: Re: Flattening a tree
From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx>
Date: Fri, 14 Jul 2000 11:45:14 +0100
Pierre-Yves,

>Does anyone know how it would be possible to transform a (sub)tree into a
>flat list of some of its elements (those considered not "inline"), mixing
>cdata and subelements.

Just to expand on Mike's solution a little, here are two templates that
operate in 'flatten mode'.

The first matches any element.  If it is an element that contains
subelements, then it simply applies templates (again in flatten mode) on
its children (both elements and text, if there is any).  If it is an
element that does not contain any subelements - in other words a #PCDATA
element or an EMPTY element - then it makes a copy of itself.

<xsl:template match="*" mode="flatten">
  <xsl:choose>
    <xsl:when test="*"><xsl:apply-templates mode="flatten" /></xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="." />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The second template matches any text node and (so long as it isn't empty),
places its (normalised) content into an element with the name of its parent
element (as in Mike's solution).

<xsl:template match="text()" mode="flatten">
  <xsl:if test="normalize-space(.) != ''">
    <xsl:element name="{name(..)}">
      <xsl:value-of select="normalize-space(.)" />
    </xsl:element>
  </xsl:if>
</xsl:template>

So, to flatten the content of a particular element, apply templates in
flatten mode on its children.  In your example:

<xsl:template match="document">
  <document>
    <xsl:apply-templates mode="flatten" />
  </document>
</xsl:template>

This gives the result you wanted in SAXON.

I hope that helps,

Jeni


Dr Jeni Tennison
Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE
Telephone 0115 9061301 ? Fax 0115 9061304 ? Email
jeni.tennison@xxxxxxxxxxxxxxxx



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread