Attribute wildcard

Considering the following XML document

media-example-1.xml

If you use the following xpath statement - 

//*[starts-with(@*, '/v1/assets/')]

using - <xsl:template match="//*[starts-with(@*, '/v1/assets/')]"/>

it only finds the attribute of the first element even though our goal was to get all elements with the same attribute value wildcard

If you swap the elements as shown in this document

media-example-2.xml

Using the same template match you only get the first elements attribute again.  Why?

I found this excellent answer on stack overflow

The reason why your original path expression:

//*[starts-with(@*, '/v1/assets/')]

does not work has to do with how functions in XPath 1.0 cope with more nodes than expected. The starts-with() function expects a single node as its first argument, and a string (or a node that evaluates to a string) as its second argument.

But in the expression above, starts-with() is handed a set of attribute nodes, @*, as its first argument. In this case, only the first of those attribute nodes is used by this function. All other nodes in the set are ignored. Since the order of attributes is not defined in XML, the XPath engine is free to choose any attribute node to be used in the function. But your specific XPath engine (and many others) appear to consistently use the first attribute node, in the order of their appearance.

To illustrate this (and to prove it), change media-example-1.xml input document to media-example-2.xml

As you can see, I have changed the order of attributes, and the attribute containing /v1/assets/ is now the second attribute of the object element, and vice versa for the param element. Using this input document, your original XPath expression will only return the param element.

Again, this behaviour is not necessarily consistent between different XPath engines! Using other implementations of XPath might yield different results.

 

The XPath expression that does what you need is

//*[@*[starts-with(., '/v1/assets/')]]

in plain English, it says

select elements anywhere in the document, but only if, among all attribute nodes of an element, there is an attribute whose value starts with "/v1/assets/".