xsl-list
[Top] [All Lists]

Re: Re: Filtering with multiple templates

2003-11-07 14:52:30

"Dongling Ding" <dling61(_at_)yahoo(_dot_)com> wrote in message
news:20031107191810(_dot_)20723(_dot_)qmail(_at_)web13908(_dot_)mail(_dot_)yahoo(_dot_)com(_dot_)(_dot_)(_dot_)
Hi Dimitre,

Thanks for the idea of merging two results together.
But the problem is those two results are generated by
program and has no certain order in there.

In my case, t1 may not be the first. If t1 is after
t2, the result of merge is

<Member name="x">
<Member name="w"/>
<Member name="z"/>
</Member>

It is not the same as the original order(z should be
before w).

I think we want to merge those template results and
also by looking at the original source to make sure
the result of merge is consistent with the original
one.

Hi Ding,

One way to achieve such merging, which will merge the elements according to
their document order, is the following:

The templates that produce the fragments to be merged must add one
additional attribute ("_pos"), the value of which is obtained using
xsl:number and reflects the document order of the copied elements.

Then when merging, we first sort the elements on the value of this
attributes and then copy them in the sorted order.

An example transformation is below. The two variables "vO1" and "vO2"
contain the results of applying templates.

The contents of "vO1" is:

<Member name="x">
   <Member name="w" _pos="6"/>
</Member>

The contents of "vO2" is:

<Member name="x">
   <Member name="z" _pos="3"/>
</Member>

Although the latter is merged to the former, their children are sorted on
the value of the "_pos" attribute before they are copied to the output.

Here's the complete transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:ext="http://exslt.org/common";
 exclude-result-prefixes="ext">

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="vrtfO1">
      <xsl:apply-templates select="Member" mode="m2"/>
    </xsl:variable>
    <xsl:variable name="vrtfO2">
      <xsl:apply-templates select="Member" mode="m1"/>
    </xsl:variable>

    <xsl:variable name="vO1" select="ext:node-set($vrtfO1)/*"/>
    <xsl:variable name="vO2" select="ext:node-set($vrtfO2)/*"/>

    <xsl:for-each select="$vO1">
      <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="* | $vO2/*">
          <xsl:sort select="@_pos" data-type="number"/>
          <xsl:copy>
            <xsl:copy-of select="@*[not(name()='_pos')]"/>
            <xsl:copy-of select="node()"/>
          </xsl:copy>
        </xsl:for-each>
      </xsl:copy>

    </xsl:for-each>
  </xsl:template>

  <xsl:template match="Member" mode="m1">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="Member[2]" mode="copy"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Member" mode="m2">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="Member[3]" mode="copy"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Member" mode="copy">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:attribute name="_pos">
        <xsl:number count="Member" level="any"/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

When applied on this source.xml:

<Member name="x">
  <Member name="y"/>
  <Member name="z">
      <Member name="z1"/>
      <Member name="z2"/>
  </Member>
  <Member name="w"/>
</Member>

the wanted result is produced:

<Member name="x">
   <Member name="z"/>
   <Member name="w"/>
</Member>


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL




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



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