Search code examples
javaxmlxpathrsssax

what is wrong with this SAX parsing and Xpath code?


Working through Maven By Example, a book from quite a few years ago, but which is, I assume, retrieving the right versions from repositories, I'm just wondering what it going wrong with the unit testing in the first example.

We have an xml file, start thereof:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
 <channel>
 <title>Yahoo! Weather - New York, NY</title>
 <link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__NY/*http://weather.yahoo.com/forecast/10002_f.html</link>
 <description>Yahoo! Weather for New York, NY</description>
 <language>en-us</language>
 <lastBuildDate>Sat, 10 Nov 2007 8:51 pm EDT</lastBuildDate>
 <ttl>60</ttl>

 <!--************ THIS IS THE LINE WE'RE INTERESTED IN ************ -->
 <yweather:location city="New York" region="NY" country="US" />

 <yweather:units temperature="F" distance="mi" pressure="in" speed="mph" />

and this xml file is being read in via an InputStream and parsed:

    Weather weather = new Weather();
    log.info("Creating XML Reader");
    SAXReader xmlReader = createXmlReader();
    Document doc = xmlReader.read(inputStream);

    // this proves we're getting the text OK
    // String xml_text_content = doc.getStringValue();
    // log.info( "=== xml text content: |" + xml_text_content + "|" );

    log.info("Parsing XML Response");
    weather.setCity(doc.valueOf("/rss/channel/y:location/@city"));
    String city_str = doc.valueOf("/rss/channel/y:location/@city");
    // this should say "New York"... but I'm getting an empty string
    log.info( "=== doc value of for city: |" + city_str + "|" );

... I know very little about RSS and XPath, sorry. Just seems like someone knowledgeable might see the problem!

PS I tried changing "yweather:location" to "y:location" in the xml file, and then "y:location" to "yweather:location" in the code... both threw exceptions. Latter case:

528 INFO YahooParser - Parsing XML Response Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.096 sec <<< FAILURE! testParser(org.sonatype.mavenbook.custom.weather.yahoo.YahooParserTest) Time el apsed: 0.094 sec <<< ERROR!
org.dom4j.XPathException: Exception occurred evaluting XPath: /rss/channel/yweather:location/@city. Exception: XPath expression uses unbound namespace prefix yweather
at org.dom4j.xpath.DefaultXPath.handleJaxenException(DefaultXPath.java:374) at org.dom4j.xpath.DefaultXPath.valueOf(DefaultXPath.java:185) at org.dom4j.tree.AbstractNode.valueOf(AbstractNode.java:191) at org.sonatype.mavenbook.custom.weather.YahooParser.parse(YahooParser.j ava:28) at org.sonatype.mavenbook.custom.weather.yahoo.YahooParserTest.testParse r(YahooParserTest.java:36)

"unbound namespace prefix yweather"...??? <gulp!>


Solution

  • Just putting in the solution (which worked for me) in case any readers of the same book have the same problem.

    On page 38 (in my edition) - section 4.3 "Creating the Simple Weather Project", we are told to run this command:

    $ mvn archetype:generate -DgroupId=org.sonatype.mavenbook.custom DartifactId=simple-weather -Dversion=1.0

    On my system (Windows 7) this created the wrong directory structure: under "main" and under "test" there was a "spurious" directory under "mavenbook": "custom".

    On page 43, when you start creating the "main" and "test" directory structures, it will be obvious to cleverer people than me that this "custom" directory shouldn't be there...

    My solution (which I arrived at finally) was indeed to get rid of this "custom" directory, make sure the paths matched OK in the import statements of the xxxxTest classes, and finally to make sure the parent pom.xml was in the same directory as directory "simple-weather" (the project pom.xml is in the latter directory).

    It is also possible to download the project ready-built (as it's meant to be, without the "custom" directory) as explained in the book...

    PS I feel it's worth the effort - if your builder/tester app doesn't work as expected where do you go from there?

    PPS It's also worth the effort in that Maven does appear to be very well-designed and powerful...