10

Is there some kind of split() function in XPath? Say I have this XML:

<root>
   <path>C:\folder\filename</path>
</root>

And I want to retrieve filename, how can I do this? I know I can get the node value like this:

//path/text()

How can I get only the filename? (I know there is a concat() function, so maybe there is a split() function?)

Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
Rise_against
  • 1,042
  • 3
  • 15
  • 36

2 Answers2

9

If you have an xpath-2.0 capable API, you can solve this in two ways:

replace technique

Try using:

fn:replace(string,pattern,replace)

e.g.

fn:replace(//path/text(),".*/","")

tokenize technique

You may get some mileage from tokenize:

fn:tokenize(string,pattern)

e.g. (thanks to Martin)

tokenize(/root/path, '\\')[last()]

w3schools xml processing "xsl functions" documentation

Vogel612
  • 5,620
  • 5
  • 48
  • 73
Alex Brown
  • 41,819
  • 10
  • 94
  • 108
  • 3
    Yes, `tokenize(/root/path, '\\')[last()]` allows that but note that both replace and tokenize are XPath 2.0 and not available in XPath 1.0 so you need an XPath 2.0 implementation like Saxon 9 (http://saxon.sourceforge.net/). – Martin Honnen Nov 23 '10 at 11:37
  • Thanks, I couldn't work out whether last applied to dynamically generated collections. – Alex Brown Nov 23 '10 at 11:39
1

While I would use:

tokenize(/*/*, '\\')[last()]

there are also numerous other ways to obtain the desired string:

  codepoints-to-string
    (reverse
      (string-to-codepoints
         (substring-before
            (codepoints-to-string
                 (reverse
                    (string-to-codepoints(/*/*)
                  )
              ),
              '\'
            )
          )
       )
     )

Or:

  substring(/*/*,
            index-of(string-to-codepoints(/*/*),
            string-to-codepoints('\')
            )
            [last()]
          + 1
           )
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431