- PR -

XPath式の記述について

1
投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-02-20 00:26
かつのりと申します。

現在Windows用のJDK1.4.2付属のDOMパーサを使用しています。
以下のようなXMLのCDATAの中身の'Hello!'を取得するようなXPath式がわかりません。
XPathによるノードの取得はorg.apache.xpath.XPathAPIを使用しています。

コード:

<test>
<test2>
<![CDATA[
Hello!
]]>
</test2>
</test>



CDATA部分がCDATAではなく、<test2>のテキストノードであれば、

コード:

<test>
<test2>
Hello!
</test2>
</test>



XPath式"test/test2/text()"で取得可能ですが、
CDATAセクションの場合に取得できません。

<test2>ノードを取得して子ノードの2番目を参照すると取得できますので、
CDATAセクションでテキストノードが分割されているようにも思えます。
(子ノードのレングスを取得すると3が返る)

Documentオブジェクトで取得可能なDOMConfigurationを使用すれば、
CDATAセクションの分割は避けられる設定を行うことは可能ですが、J2SE5からの対応みたいです。

XPath式1回でCDATAセクションの値の取得ができるXPath式があれば
教えていただけないでしょうか。
以上宜しくお願いします。


[ メッセージ編集済み 編集者: かつのり 編集日時 2005-02-20 00:28 ]
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2005-02-20 04:42
実際にコードを書いて確認していないので、以下誤りを含むかもしれません(_ _)

テキストノードを擬似的に<TEXT>で表すと、CDATA セクションを含む例の DOM 構造は以下のようになっていると考えられます。
XPath 仕様によると、CDATA セクションは中身が展開され、< 等の文字が &lt; 等に置換されたように扱われるとあるので、展開した形にしてあります。
コード:
<test>
  <test2>
     <TEXT/>
     <TEXT>Hello!</TEXT>
     <TEXT/>
  </test2>
</test>



test/test2/text() という XPath テスト式では 3 つの <TEXT> ノードが選択されますが、その最初を出力してしまうと空文字列が返ることになります。

text() はテキストノードだけを取り出すノードテスト式なので、単純に位置条件を付けてtest/test2/text()[position()=2] でいかがでしょうか。

前後の <TEXT> ノードの値が空であることを利用して、test/test2/text()[string-length() > 0] の方が良いかもしれません。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-02-20 12:28
返答ありがとうございます。
試してみたんですが、結果としては駄目でした・・・

test/test2/text()[position()=1]     nullが返る
test/test2/text()[position()=2]     CDATAの前の空白を含むテキストノードが返る
test/test2/text()[position()=3]     nullが返る
test/test2/text()[string-length() > 0] CDATAの前の空白を含むテキストノードが返る
test/test2/text()[string-length() > 30] CDATAの前の空白を含むテキストノードが返る

string-length()>30の条件を付けても
CDATAの前の空白を含むテキストノードが返る理由が不明です・・・
ちなみに「CDATAの前の空白を含むテキストノード」って言うのは
実際には30文字もありません。

コード:
<test>
    <test2>
        a<![CDATA[
            hello!
        ]]>b
    </test2>
</test>



試したXPathは上記のようなXMLでは「空白のテキストノード」の変わりに
[a]を含むテキストノードが返ってきます。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-02-20 12:39
コード:
<test>
    <test2><![CDATA[
        hello!
    ]]></test2>
</test>



上記のようなXMLなら成功しました。
タグとCDATAセクションの間に何もなければOKみたいです。
test/test2/text()
test/test2/text()[position()=1]
test/test2/text()[string-length() > 0]
でうまく取得ができました。

パーサの挙動を固定したいので、
DOM Level3を実装したパーサの使用も検討しようかなと思います。
(xerces2とか・・・)

ありがとうございました。
1

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