0

1 つの XML 文字列フィールドを含むオブジェクトのリストがあります。そのフィールドに対してSQLのようなクエリを実行し、値を満たすサブリストを取得する必要があります。XPath を使用しようとしています。

まず、これを実現するための XPath 文字列がわかりません。第二に、これを行うためのより良い方法があるかもしれません。SOを検索してみましたが、答えは実際にはこの問題に対処していません

詳細

私は本のリストを持っています:

List <Books> allBooks;

Book クラスには、id フィールドと details フィールドを含めることができます。詳細は XML です。

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

詳細 xml 文字列のサンプルを次に示します。

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

ですから、ここまではすべて石で設定されています。これは既存のコードの一部であり、その設計を変更することはできません。

私の仕事は、リストallBooksを取得してクエリを実行することです。そのロジックは次のとおりです。

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

このデータを DB に投げて実際のクエリを実行することを検討しましたが、リストには数百のレコードしか含まれないため、接続やデータの読み込みなどのオーバーヘッドは価値がありません。

XPathを介してこれを行う方法を知っている人はいますか? これを行うより良い方法はありますか?

4

3 に答える 3

1

最初に XPath クエリを作成する必要があります。それらについては、以前の回答を参照することをお勧めします (hoaz はこちらに良いリストを掲載しています)。次に、クエリをコンパイルして評価するコードを記述する必要があります。例:

  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 クエリを動的に作成することもできますが、これで基本的な考え方がわかります。

于 2012-12-05T16:31:00.780 に答える
1

帳簿が必要です

//book

著者「JKローリング」と

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

ジャンルは「ファンタジー」

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

キーワードは「ウィザード」または「ホグワーツ」

//book[author = "J K Rowling" and genre = "fantasy" and (keyword = "wizard" or keyword = "hogwarts")]
于 2012-12-05T16:03:54.210 に答える
0

Booksがルートであると仮定します

/Books/Book[(author = "J K Rowling") and (genre = "fantasy") and (keyword = "wizard" or keyword = "hogwarts")]
于 2012-12-05T16:05:28.447 に答える