- PR -

XPath式によるxml文書の検索方法 (javax.xml.xpath.XPathパッケージを利用)

1
投稿者投稿内容
未記入
会議室デビュー日: 2007/04/09
投稿数: 5
投稿日時: 2007-04-09 13:14
皆様のお知恵をお貸し下さい。

ある特定種類の要素以下に存在する属性、要素のcontains検索を実現したい
のですが、、うまくいきません。

具体的には、以下のxmlの文書でBのNodeListを取得したいと考えています。

[例] searchTextがabやcの場合NodeListには@、A両方
searchTextがb1やc1の場合NodeListには@のみ
searchTextがb2やc2の場合NodeListにはAのみ

といった感じです。

xml
----------------------------------------------------------------------------
<A>
<B attribute="ab1"> ・・・・・・@
<C>c1</C>
</B>
<B attribute="ab2"> ・・・・・・A
<C>c2</C>
</B>
</A>

source code
----------------------------------------------------------------------------

NodeList nodeList = (NodeList) xpath.evaluate(
   "/A/B[contains(ここです!,'" + searchText + "')]",
new InputSource(fileURI),
XPathConstants.NODESET);

ここです!の部分のXPath式の書き方を教えていただけると幸いです。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2007-04-09 13:24
「検索対象がattributeの値のみの場合」「検索対象がCの中身のみの場合」の書き方はわかりますか?
未記入
会議室デビュー日: 2007/04/09
投稿数: 5
投稿日時: 2007-04-09 13:36
早速のご返答ありがとうございます!

Bの属性の場合は@属性名、Bの子要素の場合は要素名をここです!の部分に書くと
属性、要素単独での検索ではうまくいきました。それで安直に*や./*、*/text()、./*/text()などを指定してみたのですが何故かBの最初の子要素(実際にはC以外にも兄弟要素が存在します)のみ検索対象となってしまい期待通りの動きになってくれません。

可能かどうかわからないのですが、Bの属性、子要素全てを一括して一つのcontainsで検索したかったのですが、、、

これでご質問の答えとなっているか自信がないのですが…

[ メッセージ編集済み 編集者: 未記入 編集日時 2007-04-09 13:50 ]
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2007-04-09 14:07
引用:

それで安直に*や./*、*/text()、./*/text()などを指定してみたのですが何故かBの最初の子要素(実際にはC以外にも兄弟要素が存在します)のみ検索対象となってしまい期待通りの動きになってくれません。



「何故か」ってことはなくて、仕様上そうなります。contains() の第一引数は
文字列が必要であり、ノードセットを文字列に変換するときは最初のノードを文字列化
したものになるからです。

引用:

可能かどうかわからないのですが、Bの属性、子要素全てを一括して一つのcontainsで検索したかったのですが、、、



Bが持ち得る属性と子要素が決まっているなら可能ですが、確定してないならXPathでは不可能だと思います。
たとえば @attribute と child::C の場合は、「@attributeに検索文字列を含むノードセット」と「child::Cに検索文字列を含むノードセット」を結合してあげればOKです。または、contains() の第一引数を「@attribute を文字列化したもの + child::C を文字列化したもの」にしてしまってもかもしれません。
ひだちのいろ
会議室デビュー日: 2007/02/14
投稿数: 9
投稿日時: 2007-04-11 02:19
横レス失礼します。
少々複雑になりますが、以下のXPathで実現できます。

(//text()|//@*)[contains(., '<searchword>')]/ancestor::B

<searchword>を検索後で置き換えて読んで下さい。
簡単に説明すると、

(//text()|//@*)

の部分が、XML文章中のすべてのテキストと属性を表します。
続く

[contains(., '<searchword>')]

で、すべてのテキストと属性のうち検索語を含むものに絞ります。
その後

/ancestor::B

で検索後を含むテキストor属性の先祖のB、すなわち子孫や属性に検索後を含むBを取り出します。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2007-04-11 08:19
おお、なるほど。「不可能」なんて書いてしまってお恥ずかしい。
1

スキルアップ/キャリアアップ(JOB@IT)