通过XML记录进行复杂的搜索查询

时间:2012-12-05 15:54:17

标签: java xml xpath

我有一个包含一个XML String字段的对象列表。我必须为该字段执行类似SQL的查询,并获得满足值的子列表。我正在尝试使用XPath。

首先,我无法找出实现此目的的XPath字符串。其次,可能有更好的方法来做到这一点。我尝试搜索SO,但答案并没有真正解决这个问题

详情

我有一份书籍清单:

List <Books> allBooks;

Book类可以有id和details字段。细节是XML。

class Book
{
    String id;
    String details; //XML
}

以下是详细信息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>

所以,在这里,它完全是一成不变的。它是现有代码的一部分,我无法改变这种设计。

我的工作是将列表全部列入&Book;通过它运行查询,其逻辑是:

   WHERE author = "J K Rowling" AND
     genre = "fantasy" AND
     (keyword = "wizard" OR keyword="hogwarts")

我考虑过在数据库中抛出这些数据来运行实际查询,但由于列表只包含几百条记录,因此连接,加载数据等的开销不值得。

任何人都知道如何通过XPath做到这一点?有没有更好的方法呢?

3 个答案:

答案 0 :(得分:1)

我们需要图书记录

//book

与作者“J K罗琳”

//book[author = "J K Rowling"]

和流派是“幻想”

//book[author = "J K Rowling" and genre = "fantasy"]

和关键字是“向导”或“hogwarts”

//book[author = "J K Rowling" and genre = "fantasy" and (keyword = "wizard" or keyword = "hogwarts")]

答案 1 :(得分:1)

您需要先构建XPath查询。我建议参考之前的答案(hoaz有一个很好的列表here)。然后,您需要编写代码来编译查询并对其进行评估。例如:

  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;
  }

你可以扩展这样的方法来接受你的查询参数来动态构建你的XPath查询,但这应该给你基本的想法。

答案 2 :(得分:0)

假设Books是根

/Books/Book[(author = "J K Rowling") and (genre = "fantasy") and (keyword = "wizard" or keyword = "hogwarts")]