Iteration

1. for-each inside an attribute value template
2. for-each inside an attribute value template
3. Select a range of nodes
4. Test for children, using for-every

1.

for-each inside an attribute value template

Michael Kay




> I need to pass parameters in a URL like: <a 
> href="page.jsp?param1=x&param2=y" /> The number of parameters is 
> unknown.

In XPath 2.0 you could use an XPath expression in your AVT containing a for expression, something like

href="{string-join(for $x in //param return concat(keyword, '=', value),
'&amp;')}"

2.

for-each inside an attribute value template

Michael Kay



> I need to pass parameters in a URL like: <a 
> href="page.jsp?param1=x&param2=y" /> The number of parameters is 
> unknown.

In XPath 2.0 you could use an XPath expression in your AVT containing a for expression, something like

... href="{string-join(for $x in //param return concat(keyword, '=', value),
'&amp;')}"

3.

Select a range of nodes

Michael Kay


 Is it possible to use Xpath to select a range of nodes.
>
> <chapter>
> <title>X</title>
> <para></para>,
> <para></para>,
> <title>Y</title>
> </chapter>
>
> I would like an Xpath statement that would select //title[1]
> THROUGH //title[2] and include all nodes between.  Is this possible?
>

I'm assuming that <para> represents <para>....</para>, i.e. a complete element.

If you know that the nodes are siblings, and you are positioned on their parent, then you can do

(title[1] , *[. >> title[1] and . << title[2]] , title[2])

If they aren't siblings and you are positioned on the root, then you can do

for $T1 in (//title)[1], $T2 in (//title)[2]
return ($T1, //*[. >> $T1 and . << $T2], $T2)

4.

Test for children, using for-every

David Carlisle



> I am unsure about the correct form of the negated expression to
> mandate that no child may have that attribute. Which variant can or
> must be used, and why?
>
> every $child in * satisfies $child[not(@my_attribute)]

The simplest way of negating an expression is to put not around it so if

every $child in * satisfies $child[@my_attribute]

is the positive test

not(every $child in * satisfies $child[@my_attribute])

is the negative test, and if that's the simplest for you to grock later than that's what I'd use.

Personally I'd have probably written the "positive test" in negative form, rather than saying every chiuld has teh attribute, say no child doesn't have the attribute not(*[not(@my_attribute)]) which is also valid xpath 1 of course. This would make your "negative" test exists(*[not(@my_attribute)]

Your other two expressions are valid but mean something else.

every $child in * satisfies $child[not(@my_attribute)]
every $child in * satisfies not($child/@my_attribute)

are true if every element does not have the attribute.

However none of the tests seem to capture what you say in english

>  all of its element children carry a specific attribute or if they don't. A
> mixed situation is to be considered as a fatal error, caught in an
> xsl:otherwise clause.

the tests you show test that all the elements have or dont have the attribute, but only test for one or the other, they don't test for the mixed case. The most direct test for the mixed test is just to test test="*[@my_attribute] and *[not(@my_attribute)]"

> Thank you very much for this hint - I actually need a test that returns
> true if all children carry the attribute AND if there are element
> children at all - maybe David's suggestion might help? (See below.)

there are always many ways of phrasing these things. It's best just to say them in english (or German or any other language of choice) in a way that makes most sense to you, and then write the xpath the same way. It's possible that some xpath variants are more efficient than others, but it's also possible that the difference isn't measurable, or that the compiler re-writes the expressions to the same internal form whatever you do, so I wouldn't worry too much about which form you use.