Re: [xsl] Algoritm for this Hierarchy?

Subject: Re: [xsl] Algoritm for this Hierarchy?
From: "Joerg Heinicke" <joerg.heinicke@xxxxxx>
Date: Sun, 3 Feb 2002 10:29:42 +0100
Hello Mario,

I have some questions about your XML:
1. You have for example {"fr"}, {"fr","un"}, {"fr","un","doo"}and
{"fr","un","doo","trois"}. Why storing one information/array multiple times?

2. And is the language always the last? It's always a bit critical, if the
output depends on the order of the input nodes. In my eyes for example it's
better to put the language as an attribute to the <p.array>-node.

3. In theory you don't need the size of an array. You can count the elements
in eery <p.array>.


Then my suggestion: You always have to select (apply-templates) the last <v>
in an array. And you must group the <p.array>s by it's last <v>.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output indent="yes"/>
<!-- grouping key -->
<xsl:key name="arrays" match="p.array" use="v[last()]"/>

<xsl:template match="r">
    <xsl:copy>
        <!-- select unique <p.array>s, grouped by it's language (last
<v>) -->
        <xsl:apply-templates select="obj/p.array[count( . |
key('arrays',v[last()])[1] ) = 1]" mode="unique"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="p.array" mode="unique">
    <!-- sort all <p.array>s with this language -->
    <xsl:apply-templates select="key('arrays', v[last()])">
        <!-- alternatively select="count(v)" if no @size-attribute -->
        <xsl:sort select="@size" order="descending"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="p.array">
    <!-- select only the <p.array> of this language with the most
entries -->
    <xsl:if test="position() = 1">
        <!-- begin with the last <v>, the language -->
        <xsl:apply-templates select="v[last()]"/>
    </xsl:if>
</xsl:template>

<xsl:template match="v">
    <obj name="{text()}">
        <!-- select the <v> backwards for order 1, 2, 3 and so on -->
        <xsl:apply-templates select="preceding-sibling::v[1]"/>
    </obj>
</xsl:template>
</xsl:stylesheet>

You get your wanted output with this stylesheet.

Regards,

Joerg

> Hello,
>
> I would like to convert the list of <obj> elements to
> the hierarchical XML output, as below, but am having
> problems identifying a workable algorithm. Can anyone
> suggest a simplest (or so ;-) algorithm for this?
>
> Mario Ruggier
>
> ===================================
> Input XML (<obj> elements may occur
> in any order):
>
> <r>
>  <obj>
>    <p.array size="1">
>      <v>en</v>
>    </p.array>
>  </obj>
>   <obj>
>    <p.array size="1">
>      <v>it</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="1">
>      <v>fr</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="2">
>      <v>one</v>
>      <v>en</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="2">
>      <v>uno</v>
>      <v>it</v>
>    </p.array>
>  </obj>
>   <obj>
>    <p.array size="2">
>      <v>un</v>
>      <v>fr</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="3">
>      <v>two</v>
>      <v>one</v>
>      <v>en</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="3">
>      <v>due</v>
>      <v>uno</v>
>      <v>it</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="3">
>      <v>doo</v>
>      <v>un</v>
>      <v>fr</v>
>    </p.array>
>  </obj>
>  <obj>
>    <p.array size="4">
>      <v>trois</v>
>      <v>doo</v>
>      <v>un</v>
>      <v>fr</v>
>    </p.array>
>  </obj>
> </r>
>
> ===================================
> Desired Output (order of sibling <obj>
> elements is not important):
>
> <r>
>   <obj name="en">
>     <obj name="one">
>       <obj name="two" />
>     </obj>
>   </obj>
>   <obj name="fr">
>     <obj name="un">
>       <obj name="doo">
>         <obj name="trois"/>
>       </obj>
>     </obj>
>   </obj>
>   <obj name="it">
>     <obj name="uno">
>       <obj name="due" />
>     </obj>
>   </obj>
> </r>


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


Current Thread