简体   繁体   中英

Parsing XML with Java XPath Query, Error:

I'm trying to learn some XML Parsing here and I've been given some code to start out with. I've done some research into the different API's i'm using and I've gradually been able to debug my code into something I hope will work. I'm trying to parse XML files by hard wiring the XPath Query's into a string variable. I'm also using DocumentBuilderFactory if that helps at all. Anyway, I keep getting this exception: Java.lang.String cannot be cast to org.w3c.dom.Node (I've marked it in the code below). I understand what the errors is. The String Query doesn't seem to agree with the parameters of the "evaluate" method. Just don't know how to fix it. I've tried all sorts of different casts and they aern't working. Something tells me I'm doing something horribly wrong here...please help! PS. I'm sorry my code is a but messy, i'm totally new to parsing, I also know there are some unnecessary imports but I figure I may need them if I make a few changes.

Code:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;

import org.jaxen.JaxenException;
import org.jaxen.dom.DOMXPath;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class Parser 
{
public static void main(String[] args) 
{
    boolean isNamespaceAware = true;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(isNamespaceAware);
    DocumentBuilder builder = null;
    try 
    {
        builder = dbf.newDocumentBuilder();
    } 
    catch (ParserConfigurationException e2)
    {
        e2.printStackTrace();
    } 
    try 
    {
        Document workingDocument =
builder.parse("C:\\Users\\Brandon\\Job\\XPath\\XPath_Sample_Stuff\\XPath_Objects.xml");
    } 
    catch (SAXException e1) 
    {
        e1.printStackTrace();
    } 
    catch (IOException e1) 
    {
        e1.printStackTrace();
    } 
    String xPathQuery = "/book/author"; 
    DOMXPath generatedPath;
    String results = null;
    try 
    {
        generatedPath = new DOMXPath(xPathQuery);
//Here is the errror
        results = generatedPath.evaluate(xPathQuery); 
    } 
    catch (JaxenException e) 
    {
        e.printStackTrace();
    }   
    if(results == null)
        System.err.println("There was an issue processing the xpath, and
 results were still null.");
    for (int i=0; i<= results.getLength();i++)
    {
        System.out.println(results.item(i));
    }
}                   

}

Here is some XML from an XML file I was given:

 <?xml version="1.0"?>
 <catalog> 
 <book id="bk101"> 
  <author>Gambardella, Matthew</author> 
  <title>XML Developer's Guide</title> 
  <genre>Computer</genre>
  <price>44.95</price>
  <publish_date>2000-10-01</publish_date> 
  <description>An in-depth look at creating applications with XML.</description> 
</book> 

The error is telling you that the DOMXPath#evaluate(...) method returns a String. You are trying to cast it as a NodeList, which it is not. The API for this method will explain all -- but again, that API is not part of standard Java but instead is part of Jaxen. But the result makes sense even for core Java since its XPath#evaluate(...) method also usually returns a String (except for one overload).

Again, perhaps you don't want to use Jaxen just now, unless you have some strong reasons for doing so but haven't told us yet.

Edit
Say you had an XML in a file, Catalog.xml, that looked like so:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<catalog>
    <book id="bk101">
        <author>Smith, John</author>
        <title>Fubars Rule</title>
        <price>100.1</price>
        <date>2012-10-01</date>
        <description>A witty exposé</description>
    </book>
    <book id="bk102">
        <author>Python, Monty</author>
        <title>Your Hovercraft is full of Eels</title>
        <price>250.5</price>
        <date>10-01-01</date>
        <description>an even wittier exposé</description>
    </book>
</catalog>

JAXB could marshall/unmarshall that sucker with just some annotations in your regular classes. It makes doing this almost idiot proof. For example:

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

public class CatalogTest {
   private static final String PATH_NAME = "Catalog.xml";



   public static void main(String[] args) {
      // comment one of the lines below and un-comment the other to test
      // marshallTest(); 
      unmarshallTest();
   }



   private static void unmarshallTest() {
      JAXBContext context;
      try {
         context = JAXBContext.newInstance(Catalog.class);
         Unmarshaller unmarshaller = context.createUnmarshaller();
         File catalogFile  = new File(PATH_NAME);
         Catalog catalog = (Catalog) unmarshaller.unmarshal(catalogFile  );
         System.out.println(catalog);
      } catch (JAXBException e) {
         e.printStackTrace();
      }

   }



   private static void marshallTest() {
      try {
         Book[] books = {
               new Book("bk101", "Smith, John", "Fubars Rule", 100.10, "2012-10-01", "A witty exposé"),
               new Book("bk102", "Python, Monty", "Your Hovercraft is full of Eels", 250.50, "10-01-01", "an even wittier exposé")
         };
         Catalog catalog = new Catalog();
         for (Book book : books) {
            catalog.addBook(book);
         }
         JAXBContext context = JAXBContext.newInstance(Catalog.class);
         Marshaller marshaller = context.createMarshaller();
         marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

         File catalogFile = new File(PATH_NAME);
         marshaller.marshal(catalog, catalogFile);

      } catch (JAXBException e) {
         e.printStackTrace();
      }
   }
}

@XmlRootElement
class Catalog {
   @XmlElement(name = "book")
   private List<Book> bookList = new ArrayList<Book>();

   public List<Book> getBookList() {
      return bookList;
   }

   public void addBook(Book book) {
      bookList.add(book);
   }

   @Override
   public String toString() {
      return "Catalog [bookList=" + bookList + "]";
   }


}

@XmlRootElement
@XmlType(propOrder = { "author", "title", "price", "date", "description"})
class Book {
   private String id;
   private String author;
   private String title;
   private double price;
   private String date;
   private String description;

   public Book() {
   }

   public Book(String id, String author, String title, double price,
         String date, String description) {
      this.id = id;
      this.author = author;
      this.title = title;
      this.price = price;
      this.date = date;
      this.description = description;
   }

   @XmlAttribute(name = "id")
   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public String getAuthor() {
      return author;
   }

   public void setAuthor(String author) {
      this.author = author;
   }

   public String getTitle() {
      return title;
   }

   public void setTitle(String title) {
      this.title = title;
   }

   public double getPrice() {
      return price;
   }

   public void setPrice(double price) {
      this.price = price;
   }

   public String getDate() {
      return date;
   }

   public void setDate(String date) {
      this.date = date;
   }

   public String getDescription() {
      return description;
   }

   public void setDescription(String description) {
      this.description = description;
   }

   @Override
   public String toString() {
      return "Book [id=" + id + ", author=" + author + ", title=" + title
            + ", price=" + price + ", date=" + date + ", description="
            + description + "]";
   }

}

If starting from scratch, I would suggest JDOM or DOM4J as alternatives (look at tutorials for both) to the Java library standard classes (org.w3c.dom.*). They are easier to work with. Jaxen will work with both of them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM