RE: Flattening a tree

Subject: RE: Flattening a tree
From: "Pierre-Yves Saumont" <pys@xxxxxxxx>
Date: Fri, 14 Jul 2000 15:24:17 +0200
Thank you very much for your answer. It helps me understanding the way the
things work.

However, the first solution is not flat enough and the second one is too
flat !

In the second case, all the elements are treated the same and everything is
flattened.

In the first case, the result is :

<document>
		content-1
		<Item>content-2</Item>
    <Item>content-3</Item>
		content-4
		<graphic/>
		content-5
	</document>

This takes off the tags but does not really flatten the structure.

At this point, I cannot think of something else than hiding the "inline"
tags, applying the second template (or Mike's one), and then unhiding the
inline tags. This is a bit complicated and should involve several pass,
somme being non-xsl, but I can't think of any better solution.

Thanks again.

Pierre-Yves


-----Message d'origine-----
De : owner-xsl-list@xxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxx]De la part de Jeni Tennison
Envoyé : vendredi 14 juillet 2000 12:45
À : Pierre-Yves Saumont
Cc : XSL-List@xxxxxxxxxxxxxxxx
Objet : Re: Flattening a tree


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


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


Current Thread