xsl-list
[Top] [All Lists]

Antw: Re: flatten a hierachy and change positions

2003-09-25 04:16:13
Hi Jenny,

thanks, I tried your examples. Just one probably very simple question is left. 
What do I have to change to keep my content, not just the elements. I assume 
with this additional part I would get both, opening and closing tags wouldn't I?

Elke



****************************************************************************************************
Elke Naraschewski - Ernst Klett Verlag GmbH Stuttgart - Leistungscenter
Mediengestaltung - Rotebühlstr.77 - 70178 Stuttgart
Tel.: 0711/6672-1116 - Fax: 0711/6672-2023 - eMail: 
e(_dot_)naraschewski(_at_)klett-mail(_dot_)de
Stuttgart HRB 10746 Verleger: Dr.h.c. Michael Klett - Geschäftsführer:
Johannes Leßmann - Harald Melcher - Dr. Tilmann Michaletz - Dr. Wolf
Unkelbach (Vorsitz)
****************************************************************************************************

jeni(_at_)jenitennison(_dot_)com 25.09.03 11:18:18 >>>
Hi Andreas,

I have to make some suppositions first, however...

You have:

  <root>
<g1>
<u1><s></s></u1>
  </g1>   <!-- I presume... -->
<g2>
<u2></u2>
</g2>
  </root>


You need:

<u1></u1>
<s></s>
<g1></g1>
<u2></u2>
<g2></g2>
  <root></root>

Correct? Needs some kind of a recursive template, I think.

You *could* also do it by iterating through all the elements in the
document, after collecting them with the path "//*":

  <xsl:for-each select="//*">
    <xsl:copy />
  </xsl:for-each>

This gives the output:

<root />
<g1 />
<u1 />
<s />
<g2 />
<u2 />

Now there's some reordering to do. I don't think that the order that
Elke originally asked for is derivable from the order of the elements
in the document, but the ordering that your recursive template gave
is: it's the order in which the end tags appear, which is the same as
the number of preceding elements + the number of descendant elements.
So you could order them with:

  <xsl:for-each select="//*">
    <xsl:sort select="count(preceding::* | descendant::*)"
              data-type="number" />
    <xsl:copy />
  </xsl:for-each>

Having said that, sorting on a count of preceding and descendant
elements is going to be pretty inefficient if you have a document of
any size, so a recursive approach similar to yours is likely to be
better. I'd do it with the single template:

<xsl:template match="*">
  <xsl:apply-templates select="*" />
  <xsl:copy />
</xsl:template>

Which says that to process an element, you process its children first
and then create a copy of the element itself.

Needs some adjustments, as I received error messages complaining
about 'Illegal values being used for attribute name' (Xalan-J
2.5.1).

The error occurs when you call the 'another' template:

<xsl:template name="another">
  <xsl:param name="parname" select="empty"/>

  <xsl:element name="{$parname}">
    <xsl:value-of select="$parname"/>
  </xsl:element>
</xsl:template>

with an empty string as the value of the $parname parameter. If
$parname is an empty string then name="{$parname}" resolves to
name="", which means that you're not supplying a name for the element
that you want created. This is an error, but an XSLT processor can
recover from it by not creating the element.

The reason that $parname is an empty string is that in the 'one'
template, you're iterating over all the children of the $parnode
using:

 <xsl:for-each select="$parnode/node()">
   <xsl:call-template name="one">
     <xsl:with-param name="parnode" select="."/>
   </xsl:call-template>
   <xsl:call-template name="another">
     <xsl:with-param name="parname" select="name(.)"/>
   </xsl:call-template>
 </xsl:for-each>

Some of the children of $parnode are likely to be text nodes; text
nodes don't have names. If you only select the element children of the
$parnode instead, with $parnode/*, then you don't get the error.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/ 


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


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



<Prev in Thread] Current Thread [Next in Thread>