How to apply the XPath function 'substring-after'

What is the XPath expression that I would use to get the string following 'HarryPotter:' for each book.

ie. Given this XML:

<bookstore>
<book>
  HarryPotter:Chamber of Secrets 
</book>
<book>
  HarryPotter:Prisoners in Azkabahn 
</book>
</bookstore>

I would get back:

Chamber of Secrets
Prisoners in Azkabahn 

I have tried something like this:

/bookstore/book/text()[substring-after(. , 'HarryPotter:')] 

I think my syntax is incorrect...

Answers


In XPath 2.0 this can be produced by a single XPath expression:

      /*/*/substring-after(., 'HarryPotter:')

Here we are using the very powerful feature of XPath 2.0 that at the end of a path of location steps we can put a function and this function will be applied on all nodes in the current result set.

In XPath 1.0 there is no such feature and this cannot be accomplished in one XPath expression.

We could perform an XSLT transformation like the following:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:for-each select="/*/*[substring-after(., 'HarryPotter:')]">
        <xsl:value-of select=
         "substring-after(., 'HarryPotter:')"/>
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>  

When applied on the original XML document:

<bookstore>
    <book>  HarryPotter:Chamber of Secrets </book>
    <book>  HarryPotter:Prisoners in Azkabahn </book>
</bookstore>

this transformation produces the wanted result:

Chamber of Secrets Prisoners in Azkabahn


In your XML you've got no space between Harry Potter but in your XQuery you've got a space. Just make it match and presto, you'll get data back...

    Dim xml = <bookstore>
                  <book>HarryPotter:Chamber of Secrets</book>
                  <book>HarryPotter:Prisoners in Azkabahn</book>
                  <book>MyDummyBook:Dummy Title</book>
              </bookstore>

    Dim xdoc As New Xml.XmlDocument
    xdoc.LoadXml(xml.ToString)

    Dim Nodes = xdoc.SelectNodes("/bookstore/book/text()[substring-after(., 'HarryPotter:')]")

    Dim Iter = Nodes.GetEnumerator()
    While Iter.MoveNext
        With DirectCast(Iter.Current, Xml.XmlNode).Value
            Console.WriteLine(.Substring(.IndexOf(":") + 1))
        End With
    End While

The XPath expression

/bookstore/book/text()[substring-after(. , 'HarryPotter:')]

will return a node set with all text nodes containing the value "HarryPotter:". To get the book title succeeding "HarryPotter:" you need to go through this node set and fetch that substring for each node. This can be done with substring-after if you're using XSLT or with Substring and IndexOf if you're using VB as shown by balabaster.


Xpath:

substring-after(//book, 'HarryPotter:')

I'm totally new in this area, but for me, it works ...!


Need Your Help

SearchView doesn't start search activity

android xml searchview

I'm trying to add a search activity using a search view in the searchbar. I've seen a few questions like this but I've tried all the answers and nothing works for me. The search show properly but w...

identify number of overlapping timespans in data frame

python pandas

I have a list of contracts with start and end dates.