xsl-list
[Top] [All Lists]

Re: [xsl] Lookup, eliminating duplicates and sorting

2006-07-22 01:25:37
Another perfect solution, I appreciate this very much, thanks again!
Manfred

On 21/07/06, Dimitre Novatchev <dnovatchev(_at_)gmail(_dot_)com> wrote:
> 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(_dot_)staudinger(_at_)gmail(_dot_)com> 
wrote:
> On 20/07/06, Mukul Gandhi <gandhi(_dot_)mukul(_at_)gmail(_dot_)com> 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(_at_)gmail(_dot_)com> 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
>
> --~------------------------------------------------------------------
> XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
> or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
> --~--
>
>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

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