JAXP 互換性ガイド
J2SE 5 Platform 用

目次

はじめに

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

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

新機能

1.4 用に作成された XML アプリケーションには、いくらかの互換性の問題があるとはいえ、J2SE 5 プラットフォームの JAXP 1.3 にはそれを上回る利点があります。

  • 組み込みのXML スキーマ検証プロセッサ
  • 他のスキーマ検証を使用可能かつjavax.xml.validation パッケージとの併用可能
  • javax.xml.datatype に XML スキーマデータ型を完全に実装。これまで Java Platform に同等のものが存在しなかったグレゴリオ暦 (太陽暦)の日時を含む
  • 高速なコンパイルトランスフォーマである XSLTC。XSLT 処理のデフォルトエンジン
  • DOM Level 3 コア。次の機能を備える
  • javax.xml.xpath での Java 中心な XPath API。XPath 表現を Java で使用しやすくなった。インタフェースを実装しているあらゆるデータモデルに適用できるように設計されていた。XPath API を使用してリファレンス実装の DOM を処理できるようになった。将来は、JDom や STAX データモデルの処理時にも利用できるようになる予定
  • XInclude の実装。ほかの箇所で再利用可能なセグメントに格納されているテキストまたは XML を使用するドキュメントをビルド可能になった
  • 文法の事前解析およびキャッシュ。大量の XML 処理では、パフォーマンスに大きく影響する
  • パーサの実装およびバージョンを知るための API。新しいライブラリのインストール時に、アプリケーションでそのライブラリが使用されているかを確認できるようになった
  • 以上が改善点です。しかし、いくつかの互換性の問題が残っています。本ドキュメントの残りの部分では、これらの問題について説明します。

    DOM Level 3

    J2SE 1.4 のリファレンス実装では DOM Level 2 API をサポートしていますが、J2SE 5 の実装では 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.3 では、処理に利用できる字句 (書式) 情報の程度を判別するためにアプリケーションが使用する 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 5 (JAXP 1.3) でも変わりません。ただし、www.saxproject.org から入手できる公式の SAX 実装では、名前空間の認識がデフォルトで「オン」になっています。JAXP の観点からは厳密には互換性の問題となりませんが、思いがけない結果を招くことがあります。

    XSLT の使用

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

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

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

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

    パッケージ名の変更

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

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

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

    システムプロパティおよび実 装クラスの使用

    アプリケーションが標準 API に存在しない機能にアクセスするには、コマンド行で -D を使ってシステムプロパティを指定しますが、このとき JRE の lib/jaxp.properties ファイル内で指定するか、またはアプリケーション内にハードコーディングして指定することが一般的です。

    JAXP 1.3 には、多くの新機能があります。そのようなアプリケーションをアップグレードするときは、同じジョブを行う javax.xml.* パッケージで標準 API を検索することをお勧めします。これは、将来のアプリケーション変更を避けるのに最善の方法です。どうしても必要な場合(機能上の制約や、新 API を検証する時間がないなど)、パッケージ名をこれまでの形式から次の形式に変換してプロパティの値を変更できます。

    org.apache.somePackage --> com.sun.org.apache.SomePackage.internal

    同様に、内部実装クラスすべてで、新しいパッケージ名を使用します。アプリケーションで実装クラスを使用している場合 (推奨されない方法)、そのようなパッケージ名も変更する必要があります。

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

    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 システムプロパティを使用して増やすことができます。