0

Within an XSL sheet, I have a nodeset in a variable, $context.

How do I properly query an attribute of the topmost node in $context? Obviously, if $context was the current node, I would just write "@attname", but it is not. Currently I do $context/../@attname which is doesn't look great to me.

EDIT

Ok, the data. Here is what I see in the VS.

In case you wonder how I got this strange thing: I UNION'ed a node with it's subnodes and an attribute selected out from a different node:

<xsl:with-param name="context" select=". | ../@res" />.

I'm not completely aware what results from this, but I can see that it works. Highlighted is the attribute I'm interested in.

Maybe that creates an attribute attached to nothing, if that makes sence at all :|

0

3 Answers 3

1
$context/../@attname

does not make too much sense. You can't go "up" here, as this would bring you "outside of" $context.

If the node-set contains something like this (a single node)

<node attname="foo">
  <bar />
</node>

then:

$context/@attname

If it is like this (a list of nodes):

<node attname="foo">
  <bar />
</node>
<node attname="foo">
  <bar />
</node>

then:

$context[1]/@attname

All of this does not work if the variable contains a result tree fragment (RTF). In this case, you need to employ an extension function called node-set(). Most XSLT processors provide this function.


EDIT: Your variable holds a union of the current node and a naked attribute node from its parent:

<xsl:with-param name="context" select=". | ../@res" />

The result of a union will always be in document order, so even though you selected the attribute after the context node in the XPath, in the resulting node set it will come before - the parent of the context node is before the context node in document order.

You need $context[1] to grab the attribute node, and $context[2] to grab the other node.

I must say that this is some strange and probably unnecessary complicated use of variables. I'm sure there is a way to do this in a less painful fashion. For example you could do

 <xsl:with-param name="context" select="." />

and then use $context/../@res in the called template. That would be a lot more straight-forward than what you are trying now.

Also, if the <xsl:with-param> you show here is part of an <xsl:call-template>, you can drop that param entirely. When a template is called (instead of applied), then the context node does not change, passing it in is redundant.

Sign up to request clarification or add additional context in comments.

9 Comments

It does make sense because first slash brings you one level down and then double-dot brings you onle level back. $context/@attname would refer to an attribute of <bar> in your example.
it will refer to the attribute of node in his example. you go one down from the node/document context same as how / selects the document element by going one down from the document context.
You can't "go up" if nodes in $context are newly created copies. If they are references to the original nodes (which is what you get if you e.g. just bind the result of any XPath expression to a variable), then .. and friends will work just fine, and will traverse the tree those nodes (still) reside in.
@GSerg: Unless you show what $context actually contains, we are forced to guess. Can you post what <xsl:copy of select="$context" /> gives?
@Pavel Minaev: Naturally. I didn't think of this. (The OP does not seem to have that in mind, though.)
|
0

In addition to tomalak's answer if you ever do need to propagate back up to the root you could try:

ancestor::*[not(..)]

Would love to hear of a situation where you might want/need this though.

Try it yourself by pasting:

//pet/ancestor::*[not(..)]

in this online Xpath test tool.

6 Comments

Tomalak's answer was the first and most natural thing that I tried. It didn't work, $context/@attname returns an empty nodeset. Whereas $context/../@attname returns the attribute value. I do not know why. But I can clearly see that in both processor results and VS debugger.
@GSerg: I have the suspicion that you might have a wrong understanding how XPath works. If I have a node <node foo="bar">, then the XPath to get the attribute is node/@foo. If that node is in a variable $x, then the XPath to get the attribute is $x/@bar.
You might well be very right. I just look at results VS gives me and try to make conclusions.
@GSerg: Ironocally, the screenshot you posted says ($context)[1] as the expression for the highlighted node right there. ;-)
Yes it does, I just didn't want to use indexing in case order ever changes :)
|
0

As you have <xsl:with-param name="context" select=". | ../@res" /> the 'res' attribute is part of the node-set (XPath 1.0) or sequence (XPath 2.0) the variable named 'context' is bound to. With XPath 2.0 you could use $context/self::attribute(res) but XPath 1.0 has no comparable expression so what you have already ($context[1] or $context/../@res) is all you can do in my view.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.