xsl-list
[Top] [All Lists]

Re: Re: Re: Filtering with multiple templates

2003-11-10 19:25:56


Hi Dimitre,

I made some progress on this merge matter. Thanks!

However, we don't know how many results we need to
merge. It depends on user's selection. So, we need to
dynamically generate the merge script you suggested
based on the user's selection.

There might just two(v1 and v2). But it may have more
than two. So, I'm trying to generate a XSLT
dynamically to handle this merge by using a java
program.

if there are v01, v02, v03, we need to do two merges.
First merge vo1 with v02 and generate the result
v_result, then merge this result with v3. And get the
final result.

Do you think this is a right way to achieve this? 


Thanks

Dongling

Please gfi

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



__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree

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



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