Reputation: 9248
I have a list of objects which contain one XML String field. I have to execute an SQL like query for that field, and get a sub list that satisfies the values. I am trying to use XPath.
Firstly, I can't figure out the XPath string to achieve this. Secondly, there might be a better way of doing this. I tried searching through SO but the answers don't really address this problem
I have a list of books:
List <Books> allBooks;
The Book class can have an id and details fields. The details is XML.
class Book
{
String id;
String details; //XML
}
Here is a sample of the details xml String:
<book>
<name>Harry Potter and the sorcerer's stone</name>
<author>J K Rowling</author>
<genre>fantasy</genre>
<keyword>wizard</keyword>
<keyword>british</keyword>
<keyword>hogwarts</keyword>
<price>25</price>
</book>
So, uptil here it is all set in stone. It is part of existing code and I cannot change that design.
My work is to take the list allBooks & run a query through it, the logic of which is:
WHERE author = "J K Rowling" AND
genre = "fantasy" AND
(keyword = "wizard" OR keyword="hogwarts")
I considered throwing this data in a DB to run an actual query, but since the list will only contain a couple of hundred records, the overhead of connection, loading data etc is not worth it.
Anyone know how to do this through XPath? Any better way of doing this?
Upvotes: 0
Views: 159
Reputation: 536
You need to build the XPath queries first. I recommend referring to a previous answer for those (hoaz has a good listing here). Then you need to write the code to compile the query and evaluate it. Example:
public List<Book> findBookInformation(List<Books> books)
throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException {
List<Book> foundBooks = new ArrayList<Book>(); // books matching criteria
for (Book book : books) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(book.details))); // parse details XML into a Doc object
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
//using one of the query examples
XPathExpression expr = xpath.compile("/book[author = \"J K Rowling\" and genre = \"fantasy\" and (keyword = \"wizard\" or keyword = \"hogwarts\")]");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
if (null != nodes && nodes.getLength() > 0) {
foundBooks.add(book); // add to your return list
}
}
return foundBooks;
}
You could extend a method like this to take in your query arguments to dynamically build your XPath query, but this should give you the basic idea.
Upvotes: 1
Reputation: 3633
Assume the Books
is the root
/Books/Book[(author = "J K Rowling") and (genre = "fantasy") and (keyword = "wizard" or keyword = "hogwarts")]
Upvotes: 0
Reputation: 10161
We need book records
//book
with author "J K Rowling"
//book[author = "J K Rowling"]
and genre is "fantasy"
//book[author = "J K Rowling" and genre = "fantasy"]
and keyword is "wizard" or "hogwarts"
//book[author = "J K Rowling" and genre = "fantasy" and (keyword = "wizard" or keyword = "hogwarts")]
Upvotes: 1