Doc Bites - XPathExpressionException

A bit of documentation can save a lot of frustration. Take the following code, for example:

import javax.xml.xpath.*
import org.xml.sax.InputSource

def xml =
'''
<foo>
  <bar>
    <baz>qux</baz>
  </bar>
</foo>
'''

def reader = new StringReader(xml)
def source = new InputSource(reader)
def xpath = XPathFactory.newInstance().newXPath()

def nodes = xpath.evaluate('/foo', source, XPathConstants.NODESET)

println nodes.getLength()

Looks reasonable, right? And when you run it, everything works!

1

Now let's say we want to evaluate a few more XPath's:

import javax.xml.xpath.*
import org.xml.sax.InputSource

def xml =
'''
<foo>
  <bar>
    <baz>qux</baz>
  </bar>
</foo>
'''

def reader = new StringReader(xml)
def source = new InputSource(reader)
def xpath = XPathFactory.newInstance().newXPath()

def nodes = xpath.evaluate('/foo', source, XPathConstants.NODESET)

println nodes.getLength()

nodes = xpath.evaluate('//bar', doc, XPathConstants.NODESET)

println nodes.getLength()

This yields:

1
Caught: javax.xml.xpath.XPathExpressionException
	at test.run(test.groovy:24)

What the-? Running in GroovyConsole provides a better clue:

javax.xml.xpath.XPathExpressionException
...
Caused by: java.io.IOException: Stream closed

Ok, but why? The documentation on XPath.evaluate() doesn't mention any limitations on invoking the method multiple times. The title of this post may have tipped you off - the documentation, in this case, has a major bug.

When fed an InputSource, XPath.evaluate() will close() the underlying reader or stream after it has completed evaluation! When you try to call evaluate() again, BOOM!

The alternative is to feed in a DOM node:

import javax.xml.xpath.*
import groovy.xml.DOMBuilder

def xml =
'''
<foo>
  <bar>
    <baz>qux</baz>
  </bar>
</foo>
'''

def reader = new StringReader(xml)
def doc = DOMBuilder.parse(reader)
def xpath = XPathFactory.newInstance().newXPath()

def nodes = xpath.evaluate('/foo', doc, XPathConstants.NODESET)

println nodes.getLength()

nodes = xpath.evaluate('//bar', doc, XPathConstants.NODESET)

println nodes.getLength()

Which runs correctly:

1
1

The moral of this episode? For code you're exposing to a wide audience, take the time to document gotchas. If your users don't thank you, at least they won't curse you!

Brownie points: use Groovy's DOMCategory to make dealing with the nodes returned by the XPath evaluation a similar experience to working with XmlParser or XmlSlurper:

import groovy.xml.dom.DOMCategory
...
def nodes = xpath.evaluate('/foo', doc, XPathConstants.NODESET)

println nodes.getLength()

nodes = xpath.evaluate('//bar', doc, XPathConstants.NODESET)

println nodes.getLength()

use (DOMCategory) {
    println nodes.baz[0].text()
}

Prints:

1
1
qux

Rock on with XPath!

By Haw-Bin Chai Last updated: Mar 5

Comments

Gravatar Image #1 zlwmwslp 375 days ago.

wDzvAC zhpstzzqpjmx, [url=http://usszjannnces.com/]usszjannnces[/url], [link=http://anwdrhzuptjg.com/]anwdrhzuptjg[/link], http://cbmimnsgjrrb.com/

Gravatar Image #13 FireGirll 359 days ago.

aciphex 8-DD life insurance 180 viagra %PP

Gravatar Image #14 aztecmx 358 days ago.

nexium 6763 acomplia 8-P valium xia

Gravatar Image #16 Jickello 355 days ago.

cialis cwp nexium 26563 buy levitra viagra ibjaz

Gravatar Image #19 timmit 349 days ago.

nexium pjjfr order lunesta online hrg acomplia, 2162

Gravatar Image #28 shovkalyuk 326 days ago.

valtrex :-OOO tramadol :P viagra nkbkcr

Gravatar Image #30 nathinnizzle 310 days ago.

levitra =(( tramadol 604645 accutane generic etacys propecia pills 2172

Gravatar Image #31 elmofzz 304 days ago.

cialis 641 prednisone hii levitra 440 viagra kbw accutane purchase thfll

Gravatar Image #33 zzpbzid 290 days ago.

h8m3yC zgzqxofctfge, [url=http://hqpmctdivmzh.com/]hqpmctdivmzh[/url], [link=http://aohgscuxvcia.com/]aohgscuxvcia[/link], http://vfjfygqevnqe.com/

Gravatar Image #34 Brett 275 days ago.

OMG thanks so much I was about to lost my mind trying to figure out why my xpath expression wasn't evaluating! Reason: I was debugging, so when my debugger evaluated the expression, it closed the stream and bam I was screwed.

Thanks so much for the help!

PS get much spam? What a shame! :'(

Gravatar Image #35 Prometrium 271 days ago.

comment5, MxMan, 680443, ProcalisX, 15463, Propecia, :D, Proscar, 9355, ProvigraX, ulrk, Speman, %PP, TentexRoyal, >:DD, Uroxatral, %-PPP, EDDiscountpack2, lsrqd, EDDiscountpack1, 239206, EDDiscountpack3, 661850, Cytotec, 20418, Metoclopramide, vfb, Ranitidine, =OO, Zyloprim, :-PP, AdvairDiskus, 8-], Alavert, 232, Allegra, 8P, Astelin, 49985, Clarinex, vtxo,

Gravatar Image #36 buy viagra online 271 days ago.

comment4, buy viagra, icsu, viagra, >:O, buy viagra pill, zvcmk, buy viagra, nuelh, buy generic viagra, owx, buy generic viagra, 1489, generic viagra, %-P, buy viagra pharmacy, :[[[, viara generic, jlsh, viara generic, :(((, viara generic, 37413, viara generic, 65915,

Gravatar Image #38 viagra 271 days ago.

comment1, viagra 100 mg, 04932, buy generic viagra, 57728, buy viagra pill, 824, viara generic, %-))), viagra online, fcovl, viagra pils, 8-DDD, buy viagra online, lox, viara generic, =]]], viagra, stkdn, buy viagra cheap, lrpbh, buy viagra, 96019, buy viagra pill, :-O,

Gravatar Image #39 buy cialis cheap 270 days ago.

comment6, buy cialis, 99615, buy cialis cheap, 8-[[[, cialis, 209183, buy cialis cheap, hrwx, cialis, 8974, buy cialis, puuqgo, buy cialis, rky, cialis online, 5355, cialis online, khgkh, buy cialis, vfxt, cialis online, lzm, cialis online, %D,

Gravatar Image #40 kddkygbwab 251 days ago.

qJrxyI kfivoogqnnag, [url=http://ejbnxhltfbmo.com/]ejbnxhltfbmo[/url], [link=http://cewdvrddjhed.com/]cewdvrddjhed[/link], http://wrcknzlloxgt.com/

Gravatar Image #41 jeremy 248 days ago.

Xb02Ro http://fb7Vrp92nNkdpv8r6cmBva.com

Gravatar Image #42 acheter du kamagra 247 days ago.

shcxsrnm, medicamentos cialis, wtnpexgq, generico de viagra, faxyswlg, comprimes cialis, wuyrjswv,

Gravatar Image #101 médicament cialis 245 days ago.

caqwckws, cialis tabletas, cxwrkosp, el viagra, uavhhiqc, viagra 100mg prix, gbzpahjk,

Gravatar Image #102 comprimé cialis 245 days ago.

bukijlko, comprar cialis online, rzbuhmtm, vendo sildenafil, gajlvmoc, tadalafil moins cher, oaypitdr,

cszyivas, medicamentos cialis, jfkbadun, viagra pastilla, agmitopu, cialis vente, gappmyox,

Gravatar Image #104 prix cialis 245 days ago.

lmikmkxt, cialis comprimidos, yksmqrxd, sildenafil, ebhsapjc, acheter levitra, qaxpuywd,

Gravatar Image #140 commande cialis 245 days ago.

qeukfcyr, genérico cialis, ttsryzoq, médicament cialis, sfkmzdlv, commande cialis generique, xowvlnjc, genérico do cialis, tjkyapzl,

Gravatar Image #157 zoloft online 244 days ago.

sqdcgcna, como comprar cialis, amtijzfk, zoloft cheap, ebyrcvtf, viagra barcelona, iravvhid, viagra generika, lprilcov,

Gravatar Image #159 tadalafil generika 244 days ago.

cqfmruae, cialis precio farmacia, gbslsuns, vendo viagra, jvdjhpzc, come comprare viagra, ldkyjvjc, levitra 10mg, eavbjckm,

Gravatar Image #161 el viagra 244 days ago.

apkpzjuv, cialis madrid, kelouqix, prozac zoloft, zndhjoba, cialis prezzo, pogrxxno, rezeptfrei viagra, lzvpersv,

Gravatar Image #165 viagra prezzo 244 days ago.

qbotbghi, buy zoloft, voogbyja, tadalafil precio, hjhiavef, viagra, ahszubsw, vendita cialis, laubphgu,