- - PR -
javax.xml.xpath.Xpath#evaluateでClassCastException
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-04-25 01:32
Sun JRE1.5 / Xerces-J 2.7.1を使用しXMLファイルを読み込んで
XPathを評価・値を取得するクラスを作成しました。
上記のような感じの実装になっているのですが、 これを“お客様のお客様の環境”で実行すると、 XPath評価結果をNodeListに変換するところでClassCastExceptionが発生しました。 スタックトレースには 「ClassCastException: java.util.ArrayList cannot be cast to org.w3c.dom.NodeList」 と出力されています。 JAXPおよびXercesのJavadocを読む限り、 Xpath#evaluateの第三引数でXPathConstants.NODESETを指定すると、 戻り値のObject型の実体はorg.w3c.dom.NodeListになるように見受けられますし、 自社に構築した環境と個人の開発端末では私の意図通り、NodeListにキャストして値を取得することができました。 特定環境のみでの現象、かつ、発生した環境は他社が構築したという事で XPath評価の実装クラスが前述のXerces-J 2.7.1以外のものになってはいないか、と懸念しています。 現象が発生しているのはLinuxなので、 echo $CLASSPATHでパスが通っているか確認しましたが、 確かにxercesImpl-2.7.1.jarへのパスは通っていました。 現象が発生している環境の$JAVA_HOME/lib/jaxp.properiesはまだ未確認ですが、 おそらくデフォルト(未指定・プロパティファイル未作成)だと思われます。 というわけで、 ・javax.xml.xpath.Xpath#evaluateで戻り値がArrayListになる場合は有り得ますか? (ArrayListで返却するようなXMLパーサは存在しますか?) ・クラスパスで特定のXMLパーサにパスを通しても、別のXMLパーサがJAXPにマップされる可能性は有り得ますか? ・その他チェックすべき項目があれば教えてください。 前述の通り、“お客様のお客様”所有の環境ということで、 直接触れることができず、情報収集に苦労しています。 お気づきの点があればご指摘いただけると嬉しいです。 | ||||||||
|
投稿日時: 2008-04-25 09:16
ドキュメントを読む限りでは、あってはならないですね。
ここにちょっと誤解があります。xercesImpl-2.7.1.jar は XPath の実装を提供していませんので、xercesImpl-2.7.1.jar をクラスパスに入れても XPath 実装は切り替わりません。 | ||||||||
|
投稿日時: 2008-04-27 20:53
早速のご指摘ありがとうございます。
Xerces-2.7.1にはXPath実装クラスが含まれていないということでしょうか? XercesのJavadocにXPathインターフェースのドキュメントも含まれていたので Xerces内部で実装クラスが提供されているものだと思い込んでいました。 となると、意図通りに動いている環境でも 実装クラスが何なのかが正確にはわからない、とうことになりますね。 JRE1.5が提供する標準XMLパーサ(com.sun.org.apache.xerces.internal.*のXerces??)が提供するクラスが使われているのでしょうか? 引き続き調査してみます。 [ メッセージ編集済み 編集者: d@ 編集日時 2008-04-27 22:43 ] | ||||||||
|
投稿日時: 2008-05-04 01:23
まだ完全解決したわけではないのですが、中間報告です。
現象が発生している環境で java -version を実施してもらったところ、 なんとJRE1.4が稼動していることが判明しました・・・。 (JAVA_HOMEがOSデフォルトのままだった??) 正しくJRE1.5が稼動するよう修正していただいた所、 件の現象は発生しなくなり、正常稼動するようになりました。 ・・・ですが、JRE1.4だとevaluteメソッド戻り値の実態がArrayListというのが納得いかないです。 http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/xml/jaxp/JAXP-Compatibility_150.html にて J2SE1.4(JAXP1.1)→ J2SE5(JAXP1.4)移行時の互換性についてがまとめられていますが、 XPathについては
と記載されているのみで、 戻り値であるObject型の実装クラスが変更された旨の記載がありません。 現在、JAXP1.1 / CrimsonのJavadocを見つけることができていないのですが、 やはりArrayListで返却する仕様なのでしょうか? [ メッセージ編集済み 編集者: d@ 編集日時 2008-05-04 01:26 ] | ||||||||
|
投稿日時: 2008-05-04 08:32
件のClassCastExceptionが発生しているのは本当に
なのですか? jre1.4がjavax.xml.xpath.XPathFactoryやXpathをどう解決しているのでしょう? | ||||||||
|
投稿日時: 2008-05-04 21:33
ClassCastExceptionが発生している箇所は
間違いなくevaluateメソッド実行とNodeListへのキャストを実行しているところです。 出力されたスタックトレースで行番号を確認・特定しました。
みたいな感じで出力されているので、これは間違いないと思います。
JRE1.4のJavadocを確認しましたが、 確かにXPath関連のクラスが含まれていないですね・・・。 javax.xml.xpath.XPathFactoryやXpathのクラス呼び出しが正常に行われた、ということは、 やはりJAXP1.1 / Crimsonではなく、JAXP1.4が動いていたということに・・・? (そうでなければClassNotFoundExceptionになりそうなもんですし、 そもそも下位互換でエラーが発生したのであれば、version違い系のエラーが発生しそうな気が・・・) 現在、Java実行環境を好きにいじれるマシンが無いため 推測ばかりで申し訳ないのですが、引き続き調査・検証してみます。 ご指摘ありがとうございました。 |
1