Re: [xsl] Best Way to Select Following Elements With An Ancestor?

Subject: Re: [xsl] Best Way to Select Following Elements With An Ancestor?
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Sat, 22 Mar 2014 15:58:09 -0700
I suspect that something like this might be quite efficient (using
keys) in the case the search is performed for more than one descendant
of a subtree top-node:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kDescendants" match="computer//*"
           use="generate-id(ancestor::computer[1])"/>
 <xsl:template match="/*">
  <xsl:apply-templates select="computer[2]/motherboard"/>
 </xsl:template>

 <xsl:template match="computer[2]/motherboard">
  <xsl:sequence select=
  "key('kDescendants', generate-id(ancestor::computer[1]))

 [. >> current()]"/>
 </xsl:template>
</xsl:stylesheet>


When the transformation is applied on the following XML document (none
was originally provided):

<computers>
 <computer>
  <cpu ghz="3.5" unlocked="Yes">Intel i7 3770k</cpu>
  <motherboard>MSI M-Power</motherboard>
  <ram>8</ram>
  <storage>
   <hdd>1000</hdd>
   <ssd>128</ssd>
  </storage>
  <gpu group="ATI">7950</gpu>
  <psu>750</psu>
 </computer>
 <computer>
  <cpu ghz="3.5" unlocked="Yes">Intel i5 3570k</cpu>
  <motherboard>ASRock Extreme 4</motherboard>
  <ram>8</ram>
  <storage>
   <hdd>1000</hdd>
  </storage>
  <gpu group="ATI">7870</gpu>
  <psu>600</psu>
 </computer>
 <computer>
  <cpu ghz="3.5" unlocked="No">Intel i5 3550</cpu>
  <motherboard>ASRock Extreme 3</motherboard>
  <ram>8</ram>
  <storage>
   <hdd>500</hdd>
  </storage>
  <gpu group="GeForce">9600GT</gpu>
  <psu>500</psu>
 </computer>
</computers>

we get exactly the wanted result:

<ram>8</ram>
<storage>
   <hdd>1000</hdd>
  </storage>
<hdd>1000</hdd>
<gpu group="ATI">7870</gpu>
<psu>600</psu>


On Sat, Mar 22, 2014 at 5:46 AM, Eliot Kimber <ekimber@xxxxxxxxxxxx> wrote:
> I have a document where each child of the root element establishes a
> unique content with regard to the output result (in this case,
> corresponding to InDesign frames).
>
> For a given descendant of one of these elements I need to know if there
> are any following elements within the same context. So simply doing
> following::* won't work and the following elements I'm checking for need
> not be siblings of the current element.
>
> The solution I arrived at is:
>
> <xsl:variable name="myDitaAncestor" select="ancestor::dita"
> as="element()*"/>
>
>     <xsl:variable name="followingWithinDita" as="element()*"
>   select="following::*[count(ancestor::dita | $myDitaAncestor) = 1]"
>     />
>
> This works but I'm wondering if there's a better solution, either one that
> is more efficient or one that is more elegant?
>
>
> Thanks,
>
> Eliot
> bbbbb
> Eliot Kimber, Owner
> Contrext, LLC
> http://contrext.com
>



--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they
write all patents, too? :)
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.

Current Thread