プロセッサーと Java API for XML Processing (JAXP) の関係
ほとんどの場合、Java™ API for XML Processing (JAXP) を使用していたアプリケーションを、現行の API を使用するようにマイグレーションする 必要があります。
JAXP の XSLT および XPath 処理部分は、XSLT 1.0 および XPath 1.0 への参照によって 定義されています。JAXP は、XSLT 2.0 および XPath 2.0 処理に対する機能を持っていません。具体的な状況としては、 入力およびスタイルシートや式が同じであっても、XSLT 2.0 または XPath 2.0 プロセッサーは、 XSLT 1.0 または XPath 1.0 プロセッサーによって生成された結果とは異なる結果を生成します。 そのため、JAXP を使用して、現行のプロセッサーをインスタンス化することはできません。
また、JAXP は、シーケンス、XQuery 1.0 をサポートしておらず、XSLT 2.0、XPath 2.0、および XQuery 1.0 で使用可能な現行の多数のデータ型もサポートしていません。さらに、JAXP では、 入出力の形式も限られています。これらの理由により、JAXP は、XSLT 2.0 スタイルシート や XPath 2.0 および XQuery 1.0 の式の処理には適していません。
以下の例で、一般的なマイグレーション・シナリオと、 JAXP を使用して作成した場合と同等なコードを現行の API を使用して作成する方法を説明します。
API を使用した XSLT スタイルシートの処理
XFactory factory = XFactory.newInstance();
XSLTExecutable style = factory.prepareXSLT(new StreamSource("style.xsl"));
style.execute(new StreamSource("input.xml"), new StreamResult(System.out));
API を使用した XPath 式の処理
XFactory factory = XFactory.newInstance();
XPathExecutable pathExpr = factory.prepareXPath("/doc/child[@id='N1378']");
// Process input from a StreamSource
XSequenceCursor result1 = pathExpr.execute(new StreamSource("input.xml"));
// Process input from a DOM node
XSequenceCursor result2 = pathExpr.execute(new DOMSource(node));
URI 参照の解決
JAXP URIResolver インターフェースのインスタンスを 使用して XSLT document() 関数への参照を解決していた場合は、XSourceResolver インターフェースを 使用して同じことを行えます。document() 関数または fn:doc() 関数への参照を解決するには、 XSourceResolver インターフェースのインスタンスを XDynamicContext インターフェースのインスタンス の代わりに設定します。xsl:import および xsl:include 宣言を使用してインポートしたスタイルシートへの参照を 解決するには、XSourceResolver インターフェースのインスタンスを XStaticContext インターフェースの インスタンスの代わりに設定します。
final XFactory factory = XFactory.newInstance();
XSLTExecutable style = factory.prepareXSLT(new StreamSource("style.xsl"));
XDynamicContext dContext = factory.newDynamicContext();
// Create and set an instance of an anonymous inner class as the
// XSourceResolver
dContext.setSourceResolver(new XSourceResolver() {
// Create an item to use as the initial context node for
// transformations in the getSource method
private XItemView fDummyNode =
factory.getItemFactory()
.item(new StreamSource(
new StringReader("<doc/>")));
// Resolve URIs by loading the resource as an XSLT stylesheet
// and evaluating it - return the result as the Source to use
public Source getSource(String href, String base) {
java.net.URI baseURI;
try {
// Get base URI object
baseURI = new java.net.URI(base);
} catch (java.net.URISyntaxException use) {
throw new RuntimeException(use);
}
// Resolved relative reference against base URI
String resolvedURI = baseURI.resolve(href).toString();
// Prepare and execute the stylesheet
XItemView transformResult =
factory.prepareXSLT(new StreamSource(resolvedURI))
.execute(fDummyNode);
return new XItemSource(transformResult);
}
});
XSequenceCursor result = style.execute(new StreamSource("input.xml"), dContext);
拡張関数および外部関数の定義
XPath 式の評価に JAXP を使用して、 XPathFunctionResolver インターフェースのインスタンスを登録し、XPath 式が呼び出す拡張関数の実装を 提供することができました。JAXP の XSLT 部分には、同等の手段はありません。
現行の API では、 XStaticContext インターフェースのインスタンスで拡張関数を宣言し、 期待される引数のタイプと、関数の呼び出し結果の期待されるタイプを指定して、 XDynamicContext インターフェースのインスタンスで拡張関数の実装を登録できます。XSLT スタイルシート、XPath 式、および XQuery 式で、登録済みの任意の拡張関数を呼び出すことができます。
スタイルシート・パラメーターおよび外部変数の値の設定
JAXP では、 Transformer.setParameter メソッドを呼び出すことによってスタイルシート・パラメーターの初期値を指定し、 XPathVariableResolver インターフェースのインスタンスを指定することによって XPath 式の変数の値を 指定することができました。API では、 XStaticContext インターフェースの declareVariable() メソッドを使用して変数を宣言し、 変数名と変数の期待されるタイプを指定します。XDynamicContext インターフェースの bind() メソッドのいずれかを 使用して、スタイルシート・パラメーター、XPath 変数、および XQuery 外部変数の値を指定できます。
XFactory factory = XFactory.newInstance();
XStaticContext sContext = factory.newStaticContext();
// Declare the XPath variable "query-id" in the static context
QName queryIdVar = new QName("query-id");
sContext.declareVariable(queryIdVar, XTypeConstants.STRING_QNAME);
// Prepare the XPath expression
XItemFactory itemFactory = factory.getItemFactory();
XPathExecutable expr =
factory.prepareXPath("/catalog/product[id eq $query-id]", sContext);
XItemView catalog = itemFactory.item(new StreamSource("catalog.xml"));
XDynamicContext dContext = factory.newDynamicContext();
// Set the value of the "query-id" variable, and evaluate the
// expression with that variable value
dContext.bind(queryIdVar, "ID43785");
XSequenceCursor product1 = expr.execute(catalog, dContext);
// Set the value of the "query-id" variable, and evaluate the
// expression with the new variable value
dContext.bind(queryIdVar, "ID18574");
XSequenceCursor product2 = expr.execute(catalog, dContext);
ID 変換
JAXP でよく使用されていた別の操作に、ID 変換があります。 これは、ある形式から別の形式にデータを変換する場合 (例えば、 DOM ツリーをシリアライズしたり、SAX イベントから DOM ツリーを生成したりする場合) に 便利な方法です。API を使用して、ID 変換を行うことができます。例については、基本的な XSLT 操作の実行を参照してください。
準備時間と実行時間の構成
JAXP では、XSLT スタイルシートに関する 多くのランタイム構成情報 (スタイルシート・パラメーターの値、URIResolvers など) を、 変換を行うために使用されるオブジェクト (Transformer インターフェースのインスタンス および TransformerHandler インターフェースのインスタンス) に直接指定します。同様に、 JAXP では、スタイルシートおよび XPath 式の準備に関する構成情報を、 TransformerFactory クラスおよび XPathFactory クラスのインスタンスに直接指定します。
API では、 XStaticContext インターフェースのインスタンスを使用して、 スタイルシートまたは式を準備するときに必要な構成情報 (名前空間バインディング、 外部関数または変数のタイプなど) を指定することができます。 同様に、スタイルシートや式の評価に必要な構成情報 (変数の値、出力パラメーターの設定値など) を、 XDynamicContext インターフェースのインスタンスで指定できます。 これを XExecutable インターフェースおよびそのサブインターフェースのメソッドを実行する際の引数として 渡すことができます。
このように構成情報を別のオブジェクトに分離することによって、 API をよりスレッド・セーフにします。アプリケーションでは、同期をとらずに、 異なるスレッドで XExecutable インターフェースの同じインスタンスを使用することができます。このことは、 Transformer、TransformerHandler および XPathExpression インターフェースのインスタンスがスレッド・セーフ でない JAXP とは対照的です。JAXP では、これらを使用するすべてのスレッドは、 これらのオブジェクトの共有インスタンスに同期アクセスするか、または各スレッドに固有の異なるコピーを作成する 必要があります。
エラーを処理します。
JAXP では、ErrorHandler インターフェースのインスタンスを指定して、 プロセッサーがエラーにどのように対応するかを制御することができます。API では、 準備時のエラーについては XStaticContext インターフェースのインスタンスで、 実行時のエラーについては XDynamicContext インターフェースのインスタンスで、 XMessageHandler インターフェースのインスタンスを指定することによって、これを行うことができます。