質問

I want to check if there is an inline stylesheet within the document, but I am not sure how to pick descendant attributes of an element as "style" attribute could be attached to any element within the body element. This is the current xpath I write:

descendant::@*[self::@style]

But the parser throws error saying: "Unexpected token "@" after axis name". Can anyone tell me how do I fix it or there is another way of doing this? Thanks!

役に立ちましたか?

解決

So, you are looking for any element anywhere within the document that has an @style attribute I think.

If you want the element that contains the attribute you want to the following:

descendant::*[@style]

That will return all descendant elements of the current node that have an @style attribute. If you wanted the attribute itself you would be better off using something like:

descendant::*[@style]/@style

That will find you all the style attributes themselves.

他のヒント

Use this XPath: //@style, it will select all attributes style

@Kirill gave the correct answer regarding how to fix

descendant::@*[self::@style]

by using

//@style

But for those who want to know why the initial XPath doesn't work, and whether there's a variant using self:: that would work...

Remember that @ is an abbreviation for the attribute:: axis. So self::@foo is shorthand for self::attribute::foo. But syntactically, there can only be one axis in a location step. That's why the parser rejects self::@style: it has two axes.

There's something else interesting going on here. You might think you could fix the expression as follows:

//@*[self::style]

(Ignore for the moment the fact that this is needlessly more complex that //@style. You start trying expressions like this when you want all attributes except style, e.g. //@*[not(self::style)].)

This expression parses and runs without errors. The first part, //@*, matches all attribute nodes in the document. And you might think (as I did) that the predicate [self::style] will evaluate to a truthy value whenever its context node is a style attribute.

But we would be wrong. If we try it, we'll get an empty nodeset. Why? If the context node is an attribute node, and the self:: axis contains only the context node, and the attribute's name matches the name that comes after self::, shouldn't the expression in the predicate yield that attribute node as its result?

On p. 1228 of XSLT 2.0 and XPath 2.0 (4th ed.), the glossary definition of Self Axis explains:

The principal node kind of the self axis is elements, which means that when the context node is an attribute, an axis step of the form self::* or self::xyz will not select that attribute [bold emphasis mine].

However, in XPath 2.0, you can use self::attribute(style). I.e. you can use a KindTest instead of a NameTest.

Michael Kay goes into quite a bit of detail on the rules for what kinds of nodes can be matched by a NameTest on p. 695.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top