この章では、Extensible Stylesheet Language Transformation (XSLT) Processor for Javaの使用方法について説明します。
内容は次のとおりです。
内容は次のとおりです。
XSLTは、1つのXML文書を別のテキスト文書に変換するために使用できるExtensible Markup Language (XML)に基づいた言語です。たとえば、XSLTを使用してXMLデータ文書を入力として受け取り、文書の要素値に対して算術計算を実行し、計算結果を示すExtensible HyperText Markup Language (XHTML)文書を生成できます。XSLTでは、XPathはソース・ノード・ツリーの要素をナビゲートおよび処理するために使用されます。XPathは、XML文書をノードから構成されるツリーとしてモデル化します。XPathノード・ツリー内のノードのタイプは、DOMツリー内のノードのタイプに対応します。
この章では、次のWorld Wide Web Consortium (W3C)標準を十分に理解していると想定します。
Extensible Stylesheet Language (XSL)およびExtensible Stylesheet Language Transformation (XSLT)。XSLTの概要は、「関連ドキュメント」に記載されているXMLの資料を参照してください。
XSLTには現在、XSLT 2.0の草案およびXSLT 1.0勧告という2つのバージョンがあります。仕様は次の場所にあります。
XPathは、XSLTおよびその他のXML言語で使用されるナビゲーショナル言語であり、XPath 2.0の草案およびXPath 1.0勧告という2つのバージョンがあります。2つのXPathバージョンの仕様は次の場所にあります。
Oracle XML Developer's Kit (XDK) XSLT Processorは、XSLTとXPathの1.0標準、およびXSLTとXPathの2.0標準の最新草案を実装します。XDK XSLT Processorでは、XPath 2.0の関数および演算子がサポートされます。仕様は次の場所にあります。
http://www.w3.org/TR/xpath-functions/
関連項目:
XDKでサポートする標準の概要は、「Oracle XML Developer's Kit標準」を参照してください
Oracle XML Developer's Kit (XDK)はXSLT 1.0に含まれていない便利な機能をいくつか提供しています。XSLT 2.0を使用するには、次のようにスタイルシートにversion
属性を設定します。
<? xml-stylesheet version="2.0" ... ?>
XSLT 2.0の便利な機能を次に示します。
ユーザー定義関数
<xsl:function>
宣言を使用して関数を定義できます。この要素には、関数名を定義するために1つのname
属性が必要です。name
属性の値はQName
です。<xsl:function>
要素の内容は、関数の形式的な引数を指定する0個以上のxsl:param
要素と、それに続く、関数から戻される値を定義する順序コンストラクタです。
QName
はnullの名前空間を持つことができますが、ユーザー定義関数にはnull以外の名前空間が必要です。つまり、abc
が名前空間として定義されている場合、add
は有効なユーザー定義関数ではありませんが、abc:add
は有効なユーザー定義関数です。
グループ化
<xsl:for-each-group>
要素、current-group()
関数およびcurrent-grouping-key()
関数を使用して、アイテムをグループ化できます。
複数結果文書
<xsl:result-document>
要素を使用して結果ツリーを作成できます。<xsl:result-document>
要素の内容は、ツリーの文書ノードの子に対する順序コンストラクタです。
たとえば、この要素を使用すると、XML文書を入力として受け取り、別々の文書に分割できます。書籍のリストを記述するXML文書を受け取り、各書籍に関するXHTML文書を生成できます。次に、各出力文書を検証できます。
一時ツリー
XSLT 1.0のようにXSL変換の中間結果とXSL変数を文字列で表現するかわりに、これらを一連の文書ノードとして格納できます。<xsl:variable>
、<xsl:param>
および<xsl:with-param>
要素で構築できる文書ノードは、一時ツリーと呼ばれます。
文字マッピング
XSLT 1.0では、文字のエスケープを指定するには<xsl:text>
および<xsl:value-of>
要素のdisable-output-escaping
属性を使用する必要がありました。XSLT 2.0では、最上位レベルのstylesheet
要素としてマッピング文字を<xsl:character-map>
要素で宣言できます。この要素を使用して、XSLT出力に<
、>
、&
などの予約文字や無効なXML文字のあるファイルを生成できます。
関連項目:
http://www.w3.org/TR/xslt20
にあるXSLT 2.0の機能の説明と例
XDK XSLT Processorは、XML文書をXML、HTML、XHTML、テキストなどの形式の別のテキストベースの文書に変換します。プロセッサは、アプリケーション・プログラミング・インタフェース(API)を使用してプログラムから起動することも、コマンドラインから実行することもできます。XSLT Processorは、次のタスクを実行できます。
1つ以上のXSLTスタイルシートを読み取ります。プロセッサは、1つのXML入力文書に複数のスタイルシートを適用し、異なる結果を生成できます。
1つ以上の入力XML文書を読み取ります。プロセッサは、1つのスタイルシートを使用して複数のXML入力文書を変換できます。
スタイルシートのルールを入力XML文書に適用して、出力文書を構築します。出力は、Document Object Model (DOM)ツリー、出力ストリームまたは一連のSimple API for XML (SAX)イベントです。
XSLTは関数ベースの言語であり、一般に変換を実行するには入力文書およびスタイルシートのDOMを必要としますが、XDK JavaにおけるXSLTプロセッサの実装では、SAXを使用してスタイルシート・オブジェクトを作成し、より少ないリソースで効率的に変換を実行できます。このスタイルシート・オブジェクトを再利用して、スタイルシートを再解析せずに複数の文書を変換できます。
内容は次のとおりです。
図6-1に、XSLT Processor for Javaの基本設計を示します。
関連項目:
XMLParser
クラスおよびXSDBuilder
クラスの詳細は、Oracle Database XML Java APIリファレンスを参照してください
XSLT Processor for Javaのデモ・プログラムは、$ORACLE_HOME/xdk/demo/java/parser/xslt
にあります。表6-1に、XSLT Processorのテストに使用できるXMLファイルとプログラムを示します。
表6-1 XSLT Processorのサンプル・ファイル
ファイル | 説明 |
---|---|
|
ID選択とパターン・マッチングのテストに使用できるサンプルXML文書。関連付けられているスタイルシートは |
|
|
|
単純な算術の実行に使用できるサンプルXMLデータ文書。関連付けられているスタイルシートは |
|
|
|
ソース・ツリーのナンバリングのテストに使用できるサンプルXMLデータ文書。このXMLデータ文書は書籍の構造を記述します。 |
|
|
|
複合パターンで |
|
|
|
ツリーを後方検索するために |
|
|
|
様々な文字列テストと操作のテストに使用できるサンプルXMLデータ文書。関連付けられているスタイルシートは |
|
|
|
HTMLページのフレームワークを提供するスタイルシート。スタイルシートは |
|
XSL変数の使用のテストに使用できるサンプルXMLデータ文書。このXMLデータ文書は書籍の構造を記述します。関連付けられているスタイルシートは |
|
|
|
Oracle XSLT ProcessorのXSL処理機能の使用方法を簡単な例で示すサンプル・アプリケーション。このプログラムは、入力スタイルシートを使用して入力XML文書を変換します。このプログラムは、XSL変換の結果を ディレクトリ内の任意のXSLTスタイルシートを最初の引数として使用し、関連付けられている |
|
Oracle XSLT ProcessorのXSL処理機能の使用方法を簡単な例で示すサンプル・アプリケーション。このプログラムは、入力スタイルシートを使用して入力XML文書を変換します。このプログラムは、結果をストリームに出力し、 |
サンプル・プログラムのコンパイル方法および実行方法は、README
に示されています。この場合、基本的な手順は次のようになります。
XDKには、複数のXML文書にスタイルシートを適用できるコマンドラインJavaインタフェースであるoraxsl
が含まれています。$ORACLE_HOME/bin/oraxsl
および%ORACLE_HOME%\bin\oraxsl.bat
シェル・スクリプトは、oracle.xml.jaxb.oraxsl
クラスを実行します。oraxsl
を使用するには、CLASSPATH
が「XDK for Java環境の設定」の説明に従って設定されていることを確認します。
コマンドラインで次の構文を使用して、oraxsl
を起動します。
oraxsl options source stylesheet result
oraxsl
ユーティリティには、スタイルシート、変換するXMLファイルおよび結果ファイル(オプション)を指定します。結果ファイルを指定しない場合、ユーティリティは変換した文書を標準出力に送信します。複数のXML文書をスタイルシートによって変換する必要がある場合は、-l
または-d
オプションを-s
および-r
オプションとともに使用します。表6-2に、これらのオプションおよび他のオプションを示します。
表6-2 oraxslのコマンドライン・オプション
オプション | 説明 |
---|---|
|
警告を表示します。デフォルトでは、警告はオフになっています。 |
|
プログラムがエラーおよび警告を書き込むファイルを指定します。 |
|
処理するファイルをリストします。 |
|
変換するファイルが格納されているディレクトリを指定します。デフォルトの動作では、ディレクトリ内のすべてのファイルが処理されます。そのディレクトリ内にあるファイルのサブセットのみ(1つのファイルのみなど)を処理する必要がある場合は、 |
|
除外するファイルの拡張子を指定します。このオプションは |
|
含めるファイルの拡張子を指定します。このオプションは |
|
スタイルシートを指定します。 |
|
結果に使用する拡張子を指定します。 |
|
結果を保存するディレクトリを指定します。このオプションは、 |
|
パラメータをリストします。 |
|
処理に使用するスレッド数を指定します。複数のスレッドを使用すると、複数の文書を処理する際のパフォーマンスを向上させることができます。 |
|
冗長出力を生成します。プログラムは、デバッグ情報を出力します。この出力は、処理中に発生した問題の追跡に有効な場合があります。 |
|
デバッグ出力を生成します。デフォルトでは、デバッグ・モードは無効になっています。グラフィカル・ユーザー・インタフェース(GUI)版のXSLTデバッガは、Oracle JDeveloperで使用できます。 |
$ORACLE_HOME/xdk/demo/java/parser/xslt
にある様々なXMLファイルおよびスタイルシートでoraxsl
をテストできます。例6-1に、math.xml
のコンテンツを示します。
例6-2に、math.xsl
というXSLTスタイルシートを示します。
これらのファイルに対してoraxsl
ユーティリティを実行して、次の例に示すHTML出力を生成できます。
oraxsl math.xml math.xsl math.htm
例6-3に、出力ファイルmath.htm
を示します。
例6-1 math.xml
<?xml version="1.0"?> <doc> <n1>5</n1> <n2>2</n2> <div>-5</div> <mod>2</mod> </doc>
例6-2 math.xsl
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="doc"> <HTML> <H1>Test for mod.</H1> <HR/> <P>Should say "1": <xsl:value-of select="5 mod 2"/></P> <P>Should say "1": <xsl:value-of select="n1 mod n2"/></P> <P>Should say "-1": <xsl:value-of select="div mod mod"/></P> <P><xsl:value-of select="div or ((mod)) | or"/></P> </HTML> </xsl:template> </xsl:stylesheet
例6-3 math.htm
<HTML> <H1>Test for mod.</H1> <HR> <P>Should say "1": 1</P> <P>Should say "1": 1</P> <P>Should say "-1": -1</P> <P>true</P> </HTML>
内容は次のとおりです。
「XSLT Processor for Javaの使用: 概要」で説明したように、XSLT Processorで使用される基本的なクラスはDOMParser
およびXSLProcessor
です。XSL2Sample.java
デモ・プログラムは、これらのクラスを使用してXSLTスタイルシートでXML文書を変換する方法をわかりやすく示します。
次の基本手順を使用して、XSLT Processorを使用するJavaプログラムを作成します。
XSLSample.java
デモ・プログラムは、XSL変換の結果としてoracle.xml.parser.v2.XMLDocumentFragment
オブジェクトを生成する方法を示します。XMLDocumentFragment
はXML文書ツリーの一部を抽出する軽量Document
オブジェクトです。XMLDocumentFragment
クラスは、org.w3c.dom.DocumentFragment
インタフェースを実装します。
XSL2Sample.java
プログラムは、DocumentFragment
オブジェクトの生成方法を示します。XMLの変換の基本手順は、「基本的なXSL変換の実行」で説明した手順と同じです。XSLProcessor.processXSL()
メソッドに渡される引数のみ異なります。XSL2Sample.java
の次のコード部分は、DOMフラグメントを作成して標準出力に出力する方法を示します。
XMLDocumentFragment result = processor.processXSL(xsl, xml); result.print(System.out);
表6-4に、オブジェクトの操作に使用できるXMLDocumentFragment
メソッドの一部を示します。
表6-4 XMLDocumentFragmentのメソッド
メソッド | 説明 |
---|---|
|
このノードがElementである場合はその属性を含む |
|
この要素のローカル名を取得します。 |
|
この要素の名前空間URIを取得します。 |
|
現在のノードの直後のノードを取得します。 |
|
ノードの名前を取得します。 |
|
基礎となるオブジェクトの型を表すコードを取得します。 |
|
現在のノードの親を取得します。 |
|
現在のノードの直前のノードを取得します。 |
|
DOMツリーからSAXイベントを報告します。 |
内容は次のとおりです。
XSLT 1.0標準では、拡張要素および拡張関数という2種類の拡張を定義しています。XDKに提供されているXSLT処理用の拡張関数を使用すると、XSLT Processorのユーザーは、任意のJavaメソッドをXSLの式から起動できます。Oracle XSLT拡張を使用する場合、次のガイドラインに従います。
特定のプログラミング言語でXSLT拡張を定義する場合、この拡張を起動できるXSLT ProcessorでのみXSLTスタイルシートを使用できます。したがって、Javaで定義されている拡張関数を起動できるのは、JavaバージョンのXSLT Processorのみです。
組込みXSL関数で特定の問題を解決できない場合のみ、XSLT拡張を使用します。
次の項で説明するように、拡張クラスの名前空間は適切なURLから開始する必要があります。
次のOracle拡張関数は特に便利です。
<ora:output>
。<ora:output>
は、最上位レベルの要素として、またはXSLテンプレートで使用できます。最上位レベルの要素として使用する場合は、追加のname
属性がある点を除いて<xsl:output>
拡張関数と同様です。テンプレートとして使用されている場合は、追加属性use
およびhref
があります。この関数は、1つのXSL変換から複数の出力を作成するときに役立ちます。
<ora:node-set>
。結果ツリーのフラグメントをnode-setに変換します。この関数は、XSL内の既存のテキストまたは中間テキストの結果を参照してさらに変換する必要がある場合に役立ちます。
Oracle Javaの拡張関数は、次のUniversal Resource Identifier (URI)に対応する名前空間にあります。
http://www.oracle.com/XSL/Transform/java/
次の名前空間にある拡張関数は、次の形式でURIを作成できるようにJava classname
のメソッドを参照します。
http://www.oracle.com/XSL/Transform/java/classname
たとえば、次の名前空間を使用して、XSLの式からjava.lang.String
メソッドを起動できます。
http://www.oracle.com/XSL/Transform/java/java.lang.String
注意:
xsl
接頭辞を名前空間に割り当てる場合、適切なURIはxmlns:xsl="http://www.w3.org/1999/XSL/Transform"
です。その他のURIでは正しい出力を生成できません。
Javaメソッドがクラスの非staticメソッドの場合、最初のパラメータはメソッドが起動されるインスタンスとして使用され、残りのパラメータがメソッドに渡されます。ただし、拡張関数がstaticメソッドの場合、その拡張関数のすべてのパラメータが、静的関数へのパラメータとして渡されます。例6-4に、XSLTスタイルシートでのjava.lang.Math.ceil()
メソッドの使用例を示します。
たとえば、例6-4をスタイルシートceil.xsl
として作成し、任意の整形式XML文書に適用できます。たとえば、次のようにoraxsl
ユーティリティを実行します。
oraxsl ceil.xsl ceil.xsl ceil.out
出力文書ceil.out
のコンテンツは次のとおりです。
<?xml version = '1.0' encoding = 'UTF-8'?> 13
注意:
XSLクラス・ローダーは、静的に追加されたJARおよびCLASSPATH
のパス、wrapper.classpath
によって指定されたパスのみ認識します。動的に追加されたファイルはXSLT Processorで認識されません。
例6-4 XSLTスタイルシートでの静的関数の使用
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://www.oracle.com/XSL/Transform/java/java.lang.Math"> <xsl:template match="/"> <xsl:value-of select="math:ceil('12.34')"/> </xsl:template> </xsl:stylesheet>
拡張関数new
は、クラスの新しいインスタンスを作成し、コンストラクタとして動作します。例6-5では、Hello World
という値を持つ新しいString
オブジェクトを作成し、それをXSL変数str1
に格納し、大文字で出力します。
たとえば、このスタイルシートをhello.xsl
として作成し、任意の整形式XML文書に適用できます。たとえば、次のようにoraxsl
ユーティリティを実行します。
oraxsl hello.xsl hello.xsl hello.out
出力文書hello.out
のコンテンツは次のとおりです。
<?xml version = '1.0' encoding = 'UTF-8'?> HELLO WORLD
例6-5 XSLTスタイルシートでのコンストラクタの使用
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jstring="http://www.oracle.com/XSL/Transform/java/java.lang.String"> <xsl:template match="/"> <!-- creates a new java.lang.String and stores it in the variable str1 --> <xsl:variable name="str1" select="jstring:new('HeLlO wOrLd')"/> <xsl:value-of select="jstring:toUpperCase($str1)"/> </xsl:template> </xsl:stylesheet>
拡張関数の結果は、XSLに定義されている次の5つの型、およびXSLT 2.0で定義されている単純なXML Schemaデータ型を含むどの型でも出力できます。
NodeSet
Boolean
String
Number
Resulttree
これらのデータ型は、変数に格納したり、他の拡張関数に渡したりできます。結果の型がXSLに定義されている5つの型のうちの1つである場合、XSLの式の結果として戻すことができます。
XSLT Processorは、パラメータ数と型に基づくオーバーロードをサポートします。プロセッサは、XSLに定義されたとおりに5つのXSL型の間で暗黙的な型変換を実行します。次のデータ型間で型変換を暗黙的に実行します。また、NodeSet
から次のデータ型にも変換します。
String
Number
Boolean
Resulttree
相互に暗黙的な変換が可能な2つの型に基づくオーバーロードは許可されません。次のオーバーロードでは、String
およびNumber
は相互に暗黙的な変換が可能なため、XSLでエラーが発生します。
overloadme(int i){}
overloadme(String s){}
XSLデータ型とJavaデータ型間のマッピングは次のように行われます。
String -> java.lang.String Number -> int, float, double Boolean -> boolean NodeSet -> NodeList ResultTree -> XMLDocumentFragment
例6-6のスタイルシートは、$ORACLE_HOME/xdk/demo/java/parser/xslt
ディレクトリにあるvariable.xml
文書を解析し、<chapter>
要素の子である<title>
の値を取得します。
例6-6をgettitle.xsl
として作成し、次のようにoraxsl
を実行できます。
oraxsl gettitle.xsl gettitle.xsl variable.out
出力文書variable.out
のコンテンツは次のとおりです。
<?xml version = '1.0' encoding = 'UTF-8'?> The value of the title element is: Section Tests
例6-6 gettitle.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:parser = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.DOMParser" xmlns:document = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.XMLDocument"> <xsl:template match ="/"> <!-- Create a new instance of the parser and store it in myparser variable --> <xsl:variable name="myparser" select="parser:new()"/> <!-- Call an instance method of DOMParser. The first parameter is the object. The PI is equivalent to $myparser.parse('file:/my_path/variable.xml'). Note that you should replace my_path with the absolute path on your system. --> <xsl:value-of select="parser:parse($myparser, 'file:/my_path/variable.xml')"/> <!-- Get the document node of the XML Dom tree --> <xsl:variable name="mydocument" select="parser:getDocument($myparser)"/> <!-- Invoke getelementsbytagname on mydocument --> <xsl:for-each select="document:getElementsByTagName($mydocument,'chapter')"> The value of the title element is: <xsl:value-of select="docinfo/title" /> </xsl:for-each> </xsl:template> </xsl:stylesheet>
この項では、XSLおよびXSLT Processor for Javaについてのヒントを示します。次の内容が含まれます。
「appendChild()を使用した文書のマージ」では、DOMでの文書のマージ方法について説明しています。マージ操作が単純な場合、XSLTベースの方法も使用できます。たとえば、例6-7および例6-8に示すXML文書をマージできます。
例6-9に、一致する<key/>
要素値に基づいて、2つのXML文書をマージするサンプル・スタイルシートを示します。
例6-7、例6-8および例6-9のXMLファイルを作成し、これをコマンドラインで実行します。
oraxsl msg_w_num.xml msgmerge.xsl msgmerge.xml
例6-10に、出力文書を示します。この文書は、msg_w_num.xml
およびmsg_w_text.xml
に含まれるデータをマージします。
この方法は、サイズが大きいファイルの場合は、2つの表間での同等のデータベースの結合ほど効果的ではありませんが、XMLファイルのみの場合は有用です。
例6-7 msg_w_num.xml
<messages> <msg> <key>AAA</key> <num>01001</num> </msg> <msg> <key>BBB</key> <num>01011</num> </msg> </messages>
例6-8 msg_w_text.xml
<messages> <msg> <key>AAA</key> <text>This is a Message</text> </msg> <msg> <key>BBB</key> <text>This is another Message</text> </msg> </messages>
例6-9 msgmerge.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <!-- store msg_w_text.xml in doc2 variable --> <xsl:variable name="doc2" select="document('msg_w_text.xml')"/> <!-- match each node in input xml document, that is, msg_w_num.xml --> <xsl:template match="@*|node()"> <!-- copy the current node to the result tree --> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- match each <msg> element in msg_w_num.xml --> <xsl:template match="msg"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <!-- insert two spaces so indentation is correct in output document --> <xsl:text> </xsl:text> <!-- copy <text> node from msg_w_text.xml into result tree --> <text><xsl:value-of select="$doc2/messages/msg[key=current()/key]/text"/> </text> </xsl:copy> </xsl:template> </xsl:stylesheet>
例6-10 msgmerge.xml
<?xml version = '1.0' encoding = 'UTF-8'?> <messages> <msg> <key>AAA</key> <num>01001</num> <text>This is a Message</text> </msg> <msg> <key>BBB</key> <num>01011</num> <text>This is another Message</text> </msg> </messages>