What is the XPath expression that I would use to get the string following \'HarryPotter:\' for each book.
ie. Given this XML:
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
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>
</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
Xpath:
substring-after(//book, 'HarryPotter:')
I'm totally new in this area, but for me, it works ...!
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.