xsl-list
[Top] [All Lists]

Re: [xsl] How to select a node in an xpath expression ?

2010-12-08 15:35:07
Vincent De Groote wrote:

[snip]
In the template matching <field-group> elements , I didn't choose an
iteration with a for-each instruction, because the for-each cannot be
"stopped" after the first match, and it could therefore produce
multiple matches.  Instead, I tried to select the correct replacement
in a variable:

<xsl:variable name='current-field-group' select='current()'/>
<xsl:variable name='replacement'
select='$replacements/replacement[field/@name =
$current-field-group/xxx:field-sequence/xxx:field[position()
&lt;=count(field)]/@name]'/>'

This expression also loops over all possible replacements and therefore 
produces multiple matches too. In both cases you can select the first match 
with the predicate [1], although I would suspect the expression to have a 
bigger chance to get optimized than a for-each followed by [1].

This replacement variable is always empty.  The expected result of
the replacement predicate is to match when the sequence of
[$replacements/replacement]/field/@name is equal to the sequence of
[$current-field-group/field-sequence/]field/@name, limiting the list
to the number of fields to be replaced.  The count(field)
sub-expression is supposed to count the number of field children of
the $replacements/replacement.

Is the last sub-expression "count(field)" understood as the count of
the $current-field-group/field-sequence field children instead of the
$replacements/replacement field children ?  If this is true, how can
i select the field children of the current replacement ?
 
Predicates are always evaluated in the context of the item to the left of the 
[, which in this case is xxx:field in this case, and obviously the count = 0. 
You can refer to the context item outside of the total expression with 
current() but AFAIK not to intermediate items (how would you specify this). So 
I think you still have to fall back to the for-each so that you can refer to 
the replacement item with current().

And by the way, your comparison wouldn't work even when count(field) could 
refer to the proper item. You are comparing two sequences of name attributes 
and this will be true if there is some value in the left one that is equal to 
some value in the right one, not when the two sequences are equal. For that you 
have to use deep-equal (fortunately you are using XSLT 2.0).

I came up with something like this. You have to adapt it to fit in your 
stylesheet. This is just to illustrate how the selection of the replacement can 
be made.

<xsl:template match="xxx:field-group">
  <xsl:variable name='current-field-group' select='current()'/>

  <xsl:variable name='replacement'>
    <xsl:for-each select="$replacements/replacement">
      <xsl:if test="deep-equal(field/@name, subsequence 
($current-field-group/xxx:field-sequence/xxx:field/@name, 1, count(field)))">
              <repl sel="{(_at_)replace-by}"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <xsl:copy-of select="$replacement/repl[1]"/>
</xsl:template>

-- 
Piet van Oostrum
Cochabamba. URL: http://pietvanoostrum.com/
Nu Fair Trade woonartikelen op http://www.zylja.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>