XPath wildcards on node name

92,724

Solution 1

This is the correct XPath 1.0 expression which selects an element with the last 5 character of name equal to "_cost" in any namespace.

/data/stats/*[substring(name(), string-length(name()) - 4) = '_cost']

Solution 2

With XPath 1.0 you can use /data/stats/*[substring-after(name(), '_cost') = ''] pattern. That checks if the element's name ends with the _cost suffix.

In XPath 2.0 there is fn:ends-with(str, str) and your corresponding expression will be *[ends-with(name(), '_cost')].

Solution 3

You could also use contains

e.g

/data/stats[contains(.,'_cost')] 

Solution 4

The above did not work for me. I had to "slightly" modify that as follows:

/data/stats/*[contains(name(),'_cost')]
Share:
92,724

Related videos on Youtube

Ben Everard
Author by

Ben Everard

I'm Ben, co-founder and developer at The Idea Bureau.

Updated on August 29, 2020

Comments

  • Ben Everard
    Ben Everard almost 4 years

    I want to grab a node from my XML file, the node has a prefix such as "latest_", but this may change and I'm keen for my XSLT to be as fluid as possible. Here's the XPath I want to use:

    /data/stats/*_cost
    

    This should match latest_cost, newest_cost, anything_cost, is there a way of doing this?

    Cheers :-)

    • Younes
      Younes over 13 years
      Depends on if XPath 2.0 is available in your environment. XPath 1.0 doesn't allow this and 2.0 does.
    • Alex Nikolaenkov
      Alex Nikolaenkov over 13 years
      As for expressions like *_cost neither XPath 1.0 nor XPath 2.0 allows them.
  • Alex Nikolaenkov
    Alex Nikolaenkov over 13 years
    . stands for all text content and this expression will match all the stats nodes which text content contains _const substring. No guarantees about postion and node names.
  • Ben Everard
    Ben Everard over 13 years
    I went with this in the end [contains(local-name(),'_cost')], it doesn't discriminate against position which is a shame, but in the context of its use that doesn't really matter.
  • Ben Everard
    Ben Everard over 13 years
    Thanks for your answer, contains worked well for me as it checked if the string exists as well. Also my environment doesn't appear to have XPath 2. Cheers anyway :-)
  • Admin
    Admin over 13 years
    as @ILMV points out, this will select an element without "_cost" in its name. Check my answer.
  • Admin
    Admin over 13 years
    This is wrong. This selects a stats element cointaining "_cost" in its string value. Check my answer.
  • Ben Everard
    Ben Everard over 13 years
    Fair point, I've input this into my application and it does what I need it to without the other disadvantages, see my comment to reqsquare. Thanks.
  • halfer
    halfer over 12 years
    +1 and thanks to @user357812 - this has been very helpful to my similar use case (matching attribute suffixes). How to do this is here if anyone is interested.
  • kletnoe
    kletnoe almost 11 years
    [substring-after(name(), '_cost') = ''] This is also true for any name() that does not contain '_cost', -1
  • Si8
    Si8 over 8 years
    I tried this: <xsl:for-each select="substring(name(.), string-length(name(.)) - 1) = 'grp'"> I get the error: ` XPTY0020: Required item type of the context item for the child axis is node(); supplied value has item type xs:boolean`
  • Dalmazio
    Dalmazio about 6 years
    For completeness, what if the user wants to search for a prefix 'cost_' instead of suffix? How would the above XPath 1.0 expression change? I'm guessing: /data/stats/*[substring(name(), 4) = 'cost_']