Re: AW: AW: [xsl] for-each with included variable

Subject: Re: AW: AW: [xsl] for-each with included variable
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 19 Apr 2001 18:41:21 +0100
Hi Renato,

> What I cannot see - due to my poor knowledge of XPath - is the semantic
> difference between: 
>
> <xsl:for-each select="(.//*[@OPTypeRef='Type1'])[1] |
> (.//*[@OPTypeRef='Type2'])[1] | (.//*[@OPTypeRef='Type3'])[1]">
>   <!-- do some stuff -->
> </xsl:for-each>

In this, you construct a node set consisting of a number of node sets
unioned together.  The first node set in the union is:

  (.//*[@OPTypeRef = 'Type1'])[1]

This gets the first descendant element of the current node whose
OPTypeRef attribute has the value 'Type1'. The second node set in the
union is:

  (.//*[@OPTypeRef = 'Type2'])[1]

This gets the first descendant element of the current node whose
OPTypeRef attribute has the value 'Type2'.  The final node set in the
union is:

  (.//*[@OPTypeRef = 'Type3'])[1]

Which similarly gets the first descendant element of the current node
whose OPTypeRef attribute has the value 'Type3'.

So, you have three node sets, each of which contains one element.
Unioning them together means you get a single node set containing
three elements - one with an OPTypeRef attribute equal to 'Type1', one
with it equal to 'Type2' and one with it equal to 'Type3'.

You iterate over this node set, so the content of the xsl:for-each is
carried out three times.

> <xsl:variable name="myOPTypeList">XType1,XType2,XType3</xsl:variable>
> <!-- global variable again -->
>
> <xsl:for-each select="(.//*[@OPTypeRef[contains($myOPTypeList, .)]])[1]">
>   <!-- do some stuff -->
> </xsl:for-each>

Here, you're selecting a single node set, consisting of the first
descendant element of the current node that has an OPTypeRef attribute
where the value of that OPTypeRef attribute is contained in the
$myOPTypeList variable.  Note that the [1] predicate at the end there
means that you just get the *first* element for which this is true.

>From the sounds of it, you want to separate the information about the
values of the OPTypeRef attributes that you want to use from XSLT code
that uses them.  It's probably easiest in this context to hold the
possible OPTypeRef attribute values in some XML rather than in a
string.  You could put it in a separate document, hold it within the
stylesheet itself, or use a variable that you convert to a node set
with a node-set() extension function, but you want to end up with a
variable that holds a set of nodes that looks something like:

   <OPType>XType1</OPType>
   <OPType>XType2</OPType>
   <OPType>XType3</OPType>

Let's say that this variable is called $myOPTypeList.  You could then
iterate over those nodes, and with each iteration pull out the
elements with the OPTypeRef attribute equal to that particular OPType.

First, you need to store the elements that you're interested in within
a variable:

  <xsl:variable name="elements" select=".//*" />

Then you want to iterate over the OPType elements in $myOPTypeList:

  <xsl:for-each select="$myOPTypeList">
     ...
  </xsl:for-each>

And then within that have another xsl:for-each that finds the first
element in the $elements variable that has a OPTypeRef attribute equal
to the value of the current OPType element:

  <xsl:for-each select="$myOPTypeList">
     <xsl:for-each select="$elements[@OPTypeRef = current()][1]">
        ...
     </xsl:for-each>
  </xsl:for-each>

As Mike suggested, you might find it more efficient to use keys rather
than searching through elements using .//*[...].  If you set up a key
that looked like:

<xsl:key name="elements" select="*[@OPTypeRef]" use="@OPTypeRef" />

then you could use:

  <xsl:for-each select="$myOPTypeList">
     <xsl:for-each select="key('elements', .)[1]">
        ...
     </xsl:for-each>
  </xsl:for-each>

But, again as Mike said, the exact key definition does depend on
whether you care about the identity of the current node.  You haven't
given us enough information about the input you're using or the
surrounding template to enable us to tell whether you do or not.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



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


Current Thread