Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: Use variables to get unique nodes

From: "Marrow" <marrow@---------.--.-->
To: NULL
Date: 10/2/2004 3:43:00 PM
Hi Rolf,

First off...

> BTW, you stated that my concat is somehow ineffective. Does this mean
> that several TEXT and VALUE-OF elements would be better ?

Yes, it is actually more efficient during execution (in all transformation
engines i have come across) to do several <xsl:text>'s and <xsl:value-of>'s
than one <xsl:value-of> with a concat().  The reason is that concat() is an
operation that takes time - and an operation that the transformation was
intending to do anyway... so you are almost doing the same thing twice by
having things like <xsl:value-of select="concat('literal',value,...)"/>.
Much the same as in many computer lanuguages - where you would avoid
concatenations - especially repeated concantenations of literal/static text.

If you reduce it to a simple test...

<?xml version="1.0"?>
<root>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <item>xxxxxxxxxxxxx</item>
  <!-- repeat a few thousand times -->
</root>

and run these two stylesheets as comparisons...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
  <xsl:for-each select="root/item">
    <xsl:text>Item: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

and...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
  <xsl:for-each select="root/item">
    <xsl:value-of select="concat('Item: ',.,'&#10;')"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

on MSXML 4.0, which you mentioned, the first stylesheet only takes only
about 30% of the time it takes for the second stylesheet.


And the main problem...

> 1) I guess macth="Pin" will match Pin at any level of what is
> currently selected.
> Right ?

Correct - so as with any match pattern you keep specifying it from right to
left until it matches the required nodes.  As you have done.

> 2) I still have some problem when I have a kind of preselection and
> the node NOT selected has also a Pin which would normally match.
> So I have made a more complex code to demonstrate that. Please find it
> below.
> (have a look to  ... select="Root/x/TEST[44 >= @Index and  @Index >=
> 43]" )
> Maybe you can explain why this happens.

You need to have a pretty good understanding of how the Muenchian technique
works... it works by saying "is this node the same as the first occurence of
these nodes with this specific value".  Therefore, any filtering needs to be
applied consistently for it to work correctly.

Filtering whilst trying to distincts can be tricky at the best of times -
and would be far more tricky (with hideously complex XPaths) if trying to
persue the preceding method of finding distincts.

If you use keys, you will be able to do some of the filtering within the
keys - by making the selection filter part of the key selection value.  And
it is as well to learn keys and become very familiar with them - as they are
extremely powerful and useful.
The down side to keys is that you cannot use variables in the @select -
which means any selective filtering needs to be placed as a value in the
select and then passed into the key() value.  Which means you could do your
@CellType and @PinClass filtering within the keys - but the comparator on
@Index would be impossible... so that would need to be added consistently as
a predicate filter.

Something like...


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="idx_from" select="43"/>
  <xsl:param name="idx_to" select="44"/>
  <xsl:param name="cell_type" select="'M'"/>
  <xsl:param name="pin_class" select="'T'"/>
  <xsl:output method="text"/>

  <!-- define a key that is capable of doing some of the filtering by
passing in key selection values -->
  <xsl:key name="kSelectPins" match="TEST/Pin"
use="concat(../@CellType,'|',@PinClass)"/>

  <!-- define the key that will filter and be used for finding distincts
with that filtering applied -->
  <xsl:key name="kDistinctPins" match="TEST/Pin"
use="concat(../@CellType,'|',@PinClass,'|',@PinName)"/>

  <xsl:variable name="TopNetPins"
select="key('kSelectPins',concat($cell_type,'|',$pin_class))[../@Index &gt;=
$idx_from and ../@Index &lt;= $idx_to]"/>
  <xsl:variable name="MultiplePins"
select="$TopNetPins[count(key('kDistinctPins',concat(../@CellType,'|',@PinCl
ass,'|',@PinName))[../@Index &gt;= $idx_from and ../@Index &lt;= $idx_to])
&gt; 1]"/>
  <xsl:variable name="UniqueMultiplePins"
select="$MultiplePins[generate-id() =
generate-id(key('kDistinctPins',concat(../@CellType,'|',@PinClass,'|',@PinNa
me))[../@Index &gt;= $idx_from and ../@Index &lt;= $idx_to])]"/>

  <xsl:template match="/">
    <xsl:text>all pins of all test nodes ==> OK&#10;</xsl:text>
    <xsl:for-each select="$TopNetPins">
      <xsl:value-of select="@PinName"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;multiple pins  ==> OK&#10;</xsl:text>
    <xsl:for-each select="$MultiplePins">
      <xsl:value-of select="@PinName"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;unique pins ==> OK&#10;</xsl:text>
    <xsl:for-each select="$UniqueMultiplePins">
      <xsl:value-of select="@PinName"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


And yes, I have used concat() a fair bit - but not for serializing output.
;)

HTH
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator



"Rolf Kemper" <KemperR@e...> wrote in message
news:bbd6fe79.0410020633.48175f09@p......
> Dear Marrow,
>
> thank you for your good input. Your code is basically working.
> But my real world is much more complex, and on top of that my
> understanding about match seems to be wrong.
> 1) I guess macth="Pin" will match Pin at any level of what is
> currently selected.
> Right ?
> 2) I still have some problem when I have a kind of preselection and
> the node NOT selected has also a Pin which would normally match.
> So I have made a more complex code to demonstrate that. Please find it
> below.
> (have a look to  ... select="Root/x/TEST[44 >= @Index and  @Index >=
> 43]" )
> Maybe you can explain why this happens.
>
> In case of fail, the $UniqueMultiplePins node set is empty !!
>
> BTW, you stated that my concat is somehow ineffective. Does this mean
> that several TEXT and VALUE-OF elements would be better ?
>
> Thank you very much for your kind help
> Rolf
>
>
> ######### new data #############################
> <?xml version="1.0" encoding="UTF-8"?>
> <Root>
> <E>
> <!-- If we have the key match with pin only
> the xslt does not work. If the maych is at least TEST/Pin
> it is OK
> -->
> <Pin PinName="A"  PinClass="T"/>
> <!--<Pin PinName="AX"  PinClass="T"/> -->
> </E>
> <x>
>     <!-- in case the TEST node below is not selected by Index
> AND PinName="A" and CellType="M" matches
> the result is wrong
> -->
> <TEST Index="42" CellType="M">
> <Pin PinName="z" PinClass="R"/>
> <!--<Pin PinName="AX" PinClass="T"/>-->
> <Pin PinName="A" PinClass="T"/>
> </TEST>
> <TEST Index="43" CellType="M">
> <Pin PinName="A" PinClass="T"/>
> <Pin PinName="D" PinClass="R"/>
> <Pin PinName="C" PinClass="R"/>
> <Pin PinName="X" PinClass="R"/>
> </TEST>
> <TEST Index="44" CellType="M">
> <Pin PinName="D" PinClass="R"/>
> <Pin PinName="C" PinClass="R"/>
> <Pin PinName="X" PinClass="R"/>
> <Pin PinName="A" PinClass="T"/>
> </TEST>
> <TEST Index="45" CellType="M">
> <Pin PinName="z" PinClass="R"/>
> </TEST>
> </x>
> </Root>
>
> ############# new xslt ############################################
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>   <xsl:output method="text"/>
>
>   <xsl:key name="kDistinctPins" match="TEST/Pin" use="@PinName"/>
>
>   <!-- @Index >= 43 fails , @Index >= 42 OK   -->
>   <xsl:variable name="Selected" select="Root/x/TEST[44 >= @Index and
> @Index >= 43]"/>
>   <xsl:variable name="Macros"  select="$Selected[@CellType='M']"/>
>   <xsl:variable name="TopNetPins"
> select="$Macros/Pin[@PinClass='T']"/>
>   <xsl:variable name="MultiplePins"
> select="$TopNetPins[count(key('kDistinctPins',@PinName)) &gt; 1]"/>
>   <xsl:variable name="UniqueMultiplePins"
> select="$MultiplePins[generate-id() =
> generate-id(key('kDistinctPins',@PinName))]"/>
>
>   <xsl:template match="/">
>     <xsl:text>all pins of all test nodes ==> OK&#10;</xsl:text>
>     <xsl:for-each select="$TopNetPins">
>       <xsl:value-of select="@PinName"/>
>       <xsl:text>&#10;</xsl:text>
>     </xsl:for-each>
>     <xsl:text>&#10;multiple pins  ==> OK&#10;</xsl:text>
>     <xsl:for-each select="$MultiplePins">
>       <xsl:value-of select="@PinName"/>
>       <xsl:text>&#10;</xsl:text>
>     </xsl:for-each>
>     <xsl:text>&#10;unique pins ==> OK&#10;</xsl:text>
>     <xsl:for-each select="$UniqueMultiplePins">
>       <xsl:value-of select="@PinName"/>
>       <xsl:text>&#10;</xsl:text>
>     </xsl:for-each>
>   </xsl:template>
> </xsl:stylesheet>
>
> ########## end ###################
>
>
> "Marrow" <marrow@s...> wrote in message
news:<Fuk7d.1464$vW1.460@n...>...
> > Hi Rolf,
> >
> > When comparing node-sets it is as well to remember that x != y is not
quite
> > the same as not(x = y).
> >
> > But anyway, I don't think it's worth trying to do what you want using
the
> > preceding method for obtaining uniques - the Muenchian technique will be
> > much easier and yield far better performance, e.g.
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <xsl:stylesheet version="1.0"
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> >   <xsl:output method="text"/>
> >
> >   <xsl:key name="kDistinctPins" match="Pin" use="@PinName"/>
> >
> >   <xsl:variable name="TestNodes" select="Root/TEST/Pin"/>
> >   <xsl:variable name="MultiplePins"
> > select="$TestNodes[count(key('kDistinctPins',@PinName)) &gt; 1]"/>
> >   <xsl:variable name="UniqueMultiplePins"
> > select="$MultiplePins[generate-id() =
> > generate-id(key('kDistinctPins',@PinName))]"/>
> >
> >   <xsl:template match="/">
> >     <xsl:text>all pins of all test nodes ==> OK&#10;</xsl:text>
> >     <xsl:for-each select="$TestNodes">
> >       <xsl:value-of select="@PinName"/>
> >       <xsl:text>&#10;</xsl:text>
> >     </xsl:for-each>
> >     <xsl:text>&#10;multiple pins  ==> OK&#10;</xsl:text>
> >     <xsl:for-each select="$MultiplePins">
> >       <xsl:value-of select="@PinName"/>
> >       <xsl:text>&#10;</xsl:text>
> >     </xsl:for-each>
> >     <xsl:text>&#10;unique pins ==> OK&#10;</xsl:text>
> >     <xsl:for-each select="$UniqueMultiplePins">
> >       <xsl:value-of select="@PinName"/>
> >       <xsl:text>&#10;</xsl:text>
> >     </xsl:for-each>
> >   </xsl:template>
> > </xsl:stylesheet>
> >
> >
> > Btw, don't overuse the concat() function - especially not for literal
> > output... you are just doing concatenation where the transformation
engine
> > will already serialize the output.
> >
> > HTH
> > Marrow
> > http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
> > http://www.topxml.com/Xselerator
> >
> >
> > "Rolf Kemper" <KemperR@e...> wrote in message
> > news:bbd6fe79.0410010704.2944868d@p......
> > > Dear Experts,
> > >
> > > I got stuck with the following problem and need your help.
> > >
> > > What I wnat to do is to get a set of distinct nodes.
> > > Before the distinct I have selected the multiple occourences already
> > > sucsessfully. However , the rest does not work as expected.
> > >
> > > Hope someone can help on that.
> > > Rolf
> > >
> > > ############################### DATA ################################
> > >
> > > My XML DATA:
> > > <?xml version="1.0" encoding="UTF-8"?>
> > > <Root>
> > > <TEST>
> > > <Pin  PinName="A" />
> > > <Pin  PinName="B" />
> > > <Pin  PinName="B" />
> > > <Pin  PinName="C" />
> > > <Pin  PinName="X" />
> > > </TEST>
> > > <TEST>
> > > <Pin  PinName="A" />
> > > <Pin  PinName="D" />
> > > <Pin  PinName="C" />
> > > <Pin  PinName="X" />
> > > <Pin  PinName="A" />
> > > </TEST>
> > > </Root>
> > >
> > >
> > > My Test XSLT:
> > > <?xml version="1.0" encoding="UTF-8"?>
> > > <xsl:stylesheet version="1.0"
> > > xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> > > xmlns:fo="http://www.w3.org/1999/XSL/Format">
> > > <xsl:output method="text"/>
> > > <xsl:variable name="NewLine" select="'&#x0d;&#x0a;'"/>
> > >
> > > <xsl:variable name="TestNodes" select="Root/TEST"/>
> > > <xsl:variable name="MultiplePins"  select="$TestNodes/Pin[@PinName =
> > > preceding::Pin/@PinName]"/>
> > > <xsl:variable name="UniqueMultiplePins"
> > > select="$MultiplePins[@PinName != preceding::*/@PinName]"/>
> > >
> > >     <xsl:template match="/">
> > >         <xsl:value-of select="concat('all pins of all test nodes ==>
> > > OK ',$NewLine)"/>
> > > <xsl:for-each select="$TestNodes/Pin">
> > > <xsl:value-of select="concat(@PinName,$NewLine)"/>
> > > </xsl:for-each>
> > > <xsl:value-of select="$NewLine"/>
> > >
> > > <xsl:value-of select="concat('multiple pins  ==> OK ',$NewLine)"/>
> > > <xsl:for-each select="$MultiplePins">
> > > <xsl:value-of select="concat(@PinName,$NewLine)"/>
> > > </xsl:for-each>
> > > <xsl:value-of select="$NewLine"/>
> > >
> > > <xsl:value-of select="concat('unique pins ==> NOT GOOD !!
> > > ',$NewLine)"/>
> > > <xsl:for-each select="$UniqueMultiplePins">
> > > <xsl:value-of select="concat(@PinName,$NewLine)"/>
> > > </xsl:for-each>
> > >
> > >     </xsl:template>
> > >
> > > </xsl:stylesheet>
> > >
> > > My results (gained by XMLSpy debug mode):
> > >
> > > all pins of all test nodes ==> OK
> > > A
> > > B
> > > B
> > > C
> > > X
> > > A
> > > D
> > > C
> > > X
> > > A
> > >
> > > multiple pins  ==> OK
> > > B
> > > A
> > > C
> > > X
> > > A
> > >
> > > unique pins ==> NOT GOOD !!
> > > B
> > > A
> > > C
> > > X
> > > A
> > >
> > > ( I expected B A C X )
> > > #################### End #################################




transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent