Re: [xsl] Lookup, eliminating duplicates and sorting

Subject: Re: [xsl] Lookup, eliminating duplicates and sorting
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Fri, 21 Jul 2006 22:46:29 -0700
I'm still fascinated by Dimitre's solution. I also tried a first modification
(but without success): <e1> represents a response from a web service,
but <e2> is supplied by me and fairly static. So it would make sense to
put it in a separate document (teste2.xml), to enable the browser to cache it.
       <e2>
               <f c="abe" b1="abc"/>
               <f c="abf" b1="abj"/>
               <f c="abg" b1="abi"/>
               <f c="abh" b1="abi"/>
       </e2>
The first key definition
  <xsl:key name="kb" match="b[not(. = ../../e2/f/@c)]"  use="."/>
I assume should become
  <xsl:key name="kb" match="b[not(.
=document('teste2.xml')/e2/f/@c)]"  use="."/>
but I have no idea how to change the second
  <xsl:key name="kb" match="@b1" use="../../../e1/b[. = current()/../@c]"/>
How can I get a xpath expression for the (primary) source document if the
context is in another source document?


Here is the solution to this problem -- it doesn't use any extension functions:

The following transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

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

<xsl:variable name="vdocInput" select="/"/>
<xsl:variable name="vdocLookup" select="document('Lookup.xml')"/>

 <xsl:key name="kDist" match="b | @b1"
  use="."/>


<xsl:template match="/">


 <xsl:variable name="vOriginal" select=
   "/*/b[not(. = $vdocLookup/e2/f/@c)]"/>

 <xsl:variable name="vunqOriginal" select=
  "$vOriginal[generate-id()
             =
              generate-id(key('kDist', .)[1])
              ]"
  />

 <xsl:variable name="vReplaced"
  select="/*/b[. = $vdocLookup/e2/f/@c]"
  />

 <xsl:variable name="vExternalValues" select=
   "$vdocLookup/e2/f/@b1
        [not(. = $vOriginal)]"
   />

 <xsl:for-each select="$vdocLookup">
	  <xsl:variable name="vunqAddedValues" select=
	   "$vExternalValues
	                  [generate-id()
	                  =
	                   generate-id(key('kDist',.)
	                                [../@c = $vReplaced][1]
	                               )
	                   ]"
	   />
	
	  <e3>
	    <xsl:for-each select="$vunqOriginal | $vunqAddedValues">
	      <xsl:sort/>
	
	        <b2><xsl:value-of select="."/></b2>
	    </xsl:for-each>
	  </e3>
 </xsl:for-each>
</xsl:template>
</xsl:stylesheet>


when applied on this source xml document:


<e1>
	<b>abc</b>
	<b>abd</b>
	<b>abf</b>
	<b>abe</b>
	<b>abh</b>
	<b>abg</b>
	<b>abd</b>
</e1>

and with the following file

Lookup.xml:
=========
<e2>
	<f c="abe" b1="abc"/>
	<f c="abf" b1="abj"/>
	<f c="abg" b1="abi"/>
	<f c="abh" b1="abi"/>
</e2>



produces the wanted result:

<e3>
  <b2>abc</b2>
  <b2>abd</b2>
  <b2>abi</b2>
  <b2>abj</b2>
</e3>



--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.






On 7/21/06, Manfred Staudinger <manfred.staudinger@xxxxxxxxx> wrote:
On 20/07/06, Mukul Gandhi <gandhi.mukul@xxxxxxxxx> wrote:
> Dimitre's solution is brilliant..
>
> Here is a solution using the node-set extension function:
Sorry, I didn't state it explicitly, I need xslt 1.0 for browsers (no
extensions),
but thanks anyway.

On 19/07/06, Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote:
> > xslt 1.0 - I've a set of nodes, for which I want
> > a. to replace some values (most will not change), then
> > b. eliminate the duplicates and sort them.
> ..............................................................................
> > The text nodes represent URI's and are then used to
> > create html links. So far I was only able to write in
> > 2 different task what should be done in one:
> >
>
>
> One simple way to do this:
>
> The following transformation:
>
> <xsl:stylesheet version="1.0"
>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>  <xsl:output omit-xml-declaration="yes" indent="yes"/>
>
>  <xsl:key name="kb" match="b[not(. = ../../e2/f/@c)]"  use="."/>
>  <xsl:key name="kb" match="@b1" use="../../../e1/b[. = current()/../@c]"/>
>   <xsl:key name="kDist" match="b | @b1" use="."/>
>
>         <xsl:template match="/">
>           <e3>
>             <xsl:for-each select="key('kb', */e1/b)[generate-id() =
>                                 generate-id(key('kDist', .)[1])]">
>               <xsl:sort/>
>
>         <b2><xsl:value-of select="."/></b2>
>       </xsl:for-each>
>           </e3>
>         </xsl:template>
> </xsl:stylesheet>
>
> when applied on the provided source xml document:
>
> <a>
>         <e1>
>                 <b>abc</b>
>                 <b>abd</b>
>                 <b>abe</b>
>                 <b>abf</b>
>                 <b>abg</b>
>                 <b>abh</b>
>                 <b>abd</b>
>         </e1>
>         <e2>
>                 <f c="abe" b1="abc"/>
>                 <f c="abf" b1="abj"/>
>                 <f c="abg" b1="abi"/>
>                 <f c="abh" b1="abi"/>
>         </e2>
> </a>
>
> produces the wanted result:
>
> <e3>
>         <b2>abc</b2>
>         <b2>abd</b2>
>         <b2>abi</b2>
>         <b2>abj</b2>
> </e3>
I'm still fascinated by Dimitre's solution. I also tried a first modification
(but without success): <e1> represents a response from a web service,
but <e2> is supplied by me and fairly static. So it would make sense to
put it in a separate document (teste2.xml), to enable the browser to cache it.
       <e2>
               <f c="abe" b1="abc"/>
               <f c="abf" b1="abj"/>
               <f c="abg" b1="abi"/>
               <f c="abh" b1="abi"/>
       </e2>
The first key definition
  <xsl:key name="kb" match="b[not(. = ../../e2/f/@c)]"  use="."/>
I assume should become
  <xsl:key name="kb" match="b[not(.
=document('teste2.xml')/e2/f/@c)]"  use="."/>
but I have no idea how to change the second
  <xsl:key name="kb" match="@b1" use="../../../e1/b[. = current()/../@c]"/>
How can I get a xpath expression for the (primary) source document if the
context is in another source document?
Regards, Manfred

Current Thread