JAXP互換性ガイドJava SE 5プラットフォーム用

目次

はじめに

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

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

新機能

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

以上が改善点です。しかし、いくつかの互換性の問題が残っています。本ドキュメントの残りの部分では、これらの問題について説明します。

DOM Level 3

Java SE 1.4のリファレンス実装ではDOM Level 2 APIをサポートしていますが、Java SE 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の間で行われた変更で、互換性に影響を及ぼす可能性のあるものは次のとおりです。

注:互換性についても説明すべき点が1つあります。Java SE 1.4 (JAXP 1.1)では、名前空間の認識は、デフォルトでオフになっていました。下位互換性のため、この方針はJava SE 5 (JAXP 1.3)でも変わりません。ただし、https://sourceforge.net/projects/sax/から入手できる公式の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ライブラリをダウンロードしてインストールし、クラス・パスに指定する必要があります。

パッケージ名の変更

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

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

  1. 内部実装にアクセスするために使用されていたプロパティ値を変更する必要がある。
  2. Xalan実装クラスから内部APIを使用していたアプリケーションでは、そのようなAPIにアクセスするためのimport文を変更する必要がある。
  3. Crimson実装から内部APIを使用していたアプリケーションは、書き直す必要がある。このとき可能であれば、新しいJAXP APIまたは、必要に応じてXerces APIを使用する。

変更点と変更の理由

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

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

JAXP 1.3参照名では、実装で使用されるApacheライブラリのパッケージ名を変更することで解決します。この変更により、クラス・パスで新しい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データを受け入れないシステムではこの問題を考慮する必要はありませんが、受け入れるシステムではこの問題を防ぐために、次のような予防手段のどれかを利用できます。


Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.