JAXP 互換性ガイド
J2SE 6 Platform 用

目次

はじめに

J2SE 1.4 プラットフォームには、JAXP 1.1 の「Crimson」リファレンス実装が含まれていました。J2SE 6 プラットフォームには、Apache 「Xerces」 ライブラリに基づく JAXP 1.4 のリファレンス実装が含まれています。

これらの実装はまったく異なるコードベースが基になっており、かつ JAXP 標準は 1.1 から 1.4 へと発展したため、どちらも JAXP 標準に準拠していますが、これらの実装間にはわずかな差異があります。これら 2 つの要因が組み合わさるために、このガイドで説明する互換性の問題が発生しています。

新機能

リリースノートを参照してください。

DOM Level 3

J2SE 1.4 のリファレンス実装では DOM Level 2 API をサポートしていますが、J2SE 6 の実装では DOM Level 3 ファミリの API をサポートしています。このセクションでは、この変更に伴う、JAXP 1.1 リファレンス実装を使用するプログラムへの影響を説明します。

詳細は、DOM Level 3 の付録 Changes にある変更点の完全な一覧を参照してください。

DOM インタフェースに追加されたメソッド

DOM Level 3 では、次のインタフェースにメソッドが追加定義されました。

追加されたメソッドにより影響を受けるのは、インタフェースを直接実装しているアプリケーションだけで、それもそのようなアプリケーションを再コンパイルしたときだけです。アプリケーションでこれらのインタフェースの実装クラスを取得するためにファクトリメソッドを使用している場合は、問題ありません。

XML 形式の保持

これらの変更の影響を受けるアプリケーションは、XML データを DOM に読み込んで変更し、元のデータ形式を保持しながら書き出すようなアプリケーションです。

JAXP 1.1 では、余分な空白は入力時に自動的に削除されました。このとき、たとえばエンティティーノードや CDATA ノードを保持するために、単一プロパティー (ignoringLexicalInfo) が false に設定されていました。これらのノードを含めることで、DOM は処理がいくらか複雑になっていました。 しかしこれらのノードが含まれているために空白出力 (インデントや新規行) が追加され、可読性が高く、書式化された、入力内容に非常に近い XML データを出力できました。

JAXP 1.4 では、処理に利用できる字句 (書式) 情報の程度を判別するためにアプリケーションが使用する API が 4 つあり、それぞれ以下の DocumentBuilderFactory メソッドを使用します。

これらのプロパティーのデフォルト値はどれも false で、受け取ったドキュメントを元の形式に再構築するために必要な字句情報がすべて保持されます。これらのプロパティーをすべて true に設定すると、もっとも単純な DOM が構築できるため、アプリケーションでは字句構文の詳細を考慮することなく、データのセマンティックコンテンツに集中することができます。

注:
新しいノードを追加するときは、可読性を高めるために必要となるインデントや新規行の書式は自動的に付加されないため、アプリケーションで付加する必要があります。

SAX 2.0.2

SAX 2.0.0 と SAX 2.0.2 で行われた変更で、互換性に影響を及ぼす可能性のあるものは以下のとおりです。

注:
互換性のある点も説明します。J2SE 1.4 (JAXP 1.1) では、名前空間の認識は、デフォルトでオフになりました。下位互換性のため、この方針は J2SE 6 (JAXP 1.4) でも変わりません。ただし、www.saxproject.org から入手できる公式の SAX 実装では、名前空間の認識がデフォルトで「オン」になっています。JAXP の観点からは厳密には互換性の問題となりませんが、思いがけない結果を招くことがあります。

XSLT の使用

標準 JAXP API を使用し、XSL トランスフォーマを作成したり XSL トランスフォーマにアクセスしたりするコードは、変更する必要がありません。出力は同じですが、たいていの場合は生成が高速になります。 これは、 Xalan トランスフォーマではなく、XSLTC のコンパイルトランスフォーマがデフォルトで使用されるためです。

注:
XSL スタイルシートの開発やテストなど、小さいデータセットで 1 回実行する場合は、Xalan と XSLTC のパフォーマンス上の大きな差はありません。しかし、大きなデータセットで XSLTC を使用する場合には、パフォーマンス上の大きな利点があります。

プログラミングによる Xalan XPath へのアクセス

JAXP 1.4 では、XPath 表現を評価するための標準 XPath API を提供します。この API を使用することをお勧めします。Xalan 解釈は、リファレンス参照に含まれていません。アプリケーションで単独の XPath 表現 (XSLT スタイルシートの一部でないもの) を評価するために Xalan XPath API を明示的に使用している場合は、Xalan 用の Apache ライブラリをダウンロードしてインストールする必要があります。

パッケージ名の変更

この変更点は、標準 JAXP API を使用するように制限されているアプリケーションには影響ありません。ただし、1.3 以前の JAXP バージョンで定義された XML プロセッサの実装固有の機能にアクセスするアプリケーションは、変更する必要があります。

変更により、従来のアプリケーションには次の影響があります。

  1. 内部実装にアクセスするために使用されていたプロパティー値を変更する必要がある

  2. Xalan 実装クラスから内部 API を使用するアプリケーションでは、そのような API にアクセスするための import 文を変更する必要がある

  3. Crimson 実装から内部 API を使用していたアプリケーションは、記録する必要がある。このとき可能であれば、新しい JAXP API または、必要に応じて Xerces API を使用する。

変更点とその理由

J2SE 1.4 では、JAXP が Java プラットフォームに組み込まれたということには利点も欠点もありました。一方、アプリケーションは、JAXP が組み込まれているという事実に依存することができました。他方、ほとんどのアプリケーションでは、以降のバージョンで入手可能になった機能やバグ修正が 必要でした。

しかし、内部クラスは常に classpath よりも優先されるため、新しいライブラリを追加しても効果はありませんでした。1.4 ではこの問題を解決するために、承認済み標準機構が使用されました。しかしその機構は新しく、アプリケーション開発者だけでなくエンドユーザーにも余分の労 力が必要とされました。

JAXP 1.3 以降では、実装で使用される Apache ライブラリのパッケージ名を変更することで解決します。この変更により、classpath で新しい Apache ライブラリを参照できるため、アプリケーション開発者はそのライブラリをこれまでと同じ方法で使用しながら、Java プラットフォームに追加されたその他の機能を利用できます。

JAXP 1.3 リファレンス実装で Apache パッケージに付けられた新しい名前は次のとおりです。

 

JAXP 1.1

Since JAXP 1.3

JAXP

org.apache.crimson

-/-
com.sun.org.apache.xerces.internal

 

org.apache.xml

com.sun.org.apache.xml.internal

XSLT

org.apache.xalan
org.apache.xpath
org.apache.xalan.xsltc

com.sun.org.apache.xalan.internal
com.sun.org.apache.xpath.internal
com.sun.org.apache.xalan.internal.xsltc

入れ子にされたエンティティー定義によるセキュリティーの問題

XML では、再帰的なエンティティー定義は認められませんが、入れ子にされたエンティティー定義は認められます。 しかし、外部ソースからの XML データを許可するサーバーがサービス妨害攻撃を受ける可能性があります。たとえば、次のように非常に深く入れ子にされたエンティティー定義が含まれる SOAP ドキュメントは、エンティティーを展開するのに CPU 時間の 100 % と大量のメモリーを消費してしまいます。

<?xml version="1.0" encoding ="UTF-8"?>
 <!DOCTYPE foobar[
 <!ENTITY x100 "foobar">
 <!ENTITY  x99 "&x100;&x100;">
 <!ENTITY  x98 "&x99;&x99;">
 ...
 <!ENTITY   x2 "&x3;&x3;">
 <!ENTITY   x1 "&x2;&x2;">
 ]>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
<SOAP-ENV:Body>
<ns1:aaa xmlns:ns1="urn:aaa" SOAP-ENV:encodingStyle="...">
<foobar xsi:type="xsd:string">&x1;</foobar>
</ns1:aaa>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope> 

外部 XML データを受け入れないシステムではこの問題を考慮する必要はありませんが、受け入れるシステムではこの問題を防ぐために、次のような予防手段のどれかを利 用することができます。

エンティティー展開を制限するための新しいシステムプロパティー
entityExpansionLimit システムプロパティーを使用すると、既存のアプリケーションは、コードを再コンパイルしなくても、エンティティー展開の総回数を制限できます。エンティティー展開の上限に達すると、パーサーは致命的なエラーをスローします (デフォルトでは、64000 に制限されています)。

システムプロパティーでエンティティー展開の上限を設定するには、Java コマンド行で次のようなオプションを使用します。-DentityExpansionLimit=100000

DTD を許可しないための新しいパーサープロパティー
アプリケーションでは、http://apache.org/xml/features/disallow-doctype-decl パーサープロパティーを true に設定することもできます。この場合、受け取った XML ドキュメントに DOCTYPE 宣言が含まれていると、致命的なエラーがスローされます。このプロパティーのデフォルト値は false です。SOAP メッセージには DTD (Document Type Declaration) を含めることができないため、一般にこのプロパティーは SOAP ベースのアプリケーションで便利です。
セキュリティー保護された処理のための新機能
JAXP 1.3 には、新しくセキュリティー保護機能が含まれているため、アプリケーションでは SAXParserFactory または DocumentBuilderFactory を設定して、セキュリティー保護された方法で動作する XML プロセッサを取得できます。この機能を true に設定すると、エンティティー展開の制限が 64000 に設定されます。デフォルトの制限は、entityExpansionLimit システムプロパティーを使用して増やすことができます。