XPath 式の評価
XPath (XML Path Language) は、XML ドキュメントからデータを取得するための XML ベースの式言語です。任意の XML ドキュメントを指定して、%XML.XPATH.DocumentOpens in a new tab クラスを使用し、簡単に XPath 式を評価できます。
使用する任意の XML ドキュメントの XML 宣言にはそのドキュメントの文字エンコードを明記する必要があり、明記しておけば、ドキュメントは宣言どおりにエンコードされるようになります。文字エンコードが宣言されていない場合、InterSystems IRIS® データ・プラットフォームでは、"入出力の文字エンコード" で説明されている既定値が使用されます。これらの既定値が正しくない場合は、XML 宣言を修正して、実際に使用されている文字セットを指定するようにします。
XPath 式の評価の概要
InterSystems IRIS XML サポートを使用して、任意の XML ドキュメントを使用して XPath 式を評価するには、次の手順を実行します。
-
%XML.XPATH.DocumentOpens in a new tab のインスタンスを作成します。そのためには、CreateFromFile()、CreateFromStream()、または CreateFromString() のいずれかのクラス・メソッドを使用します。これらのどのメソッドを使用する場合でも、入力する XML ドキュメントを最初の引数として指定し、%XML.XPATH.DocumentOpens in a new tab のインスタンスを出力パラメータとして受け取ります。
この手順によって、組み込み XSLT プロセッサを使用して XML ドキュメントが解析されます。
-
%XML.XPATH.DocumentOpens in a new tab のインスタンスの EvaluateExpression() メソッドを使用します。このメソッドには、評価するノード・コンテキストと式を指定します。
-
ノード・コンテキストは、式を評価するコンテキストを指定します。XPath 構文を使用してその目的のノードへのパスを表します。以下はその例です。
"/staff/doc"
-
評価する式にも XPath 構文を使用します。以下はその例です。
"name[@last='Marston']"
出力パラメータとして (3 番目の引数として) 結果を受け取ります。以下に例を示します。
set status=##class(%XML.XPATH.Document).CreateFromFile("c:/test/myfile.xml,.mydoc) //check status before proceeding set status=mydoc.EvaluateExpression("/staff/doc","name[@last='Marston']",.myresults) //check status before proceeding write !, myresults
-
以下のセクションでは、これらのすべてのメソッドの詳細と例を示します。
大規模なドキュメント・セットの繰り返し処理を行いつつ、それら各自の XPath 式を評価している場合、次のドキュメントを開く前に、NULL に等しいドキュメントに対する処理実行時に OREF を設定することを推奨します。これはサードパーティ・ソフトウェアの制限を回避して機能します。この制限は、大量のドキュメントをループで処理する場合において、CPU 使用量が若干増加する原因になります。
XPATH ドキュメント作成時の引数リスト
%XML.XPATH.DocumentOpens in a new tab のインスタンスを作成するには、そのクラスの CreateFromFile()、CreateFromStream()、または CreateFromString() のいずれかのクラス・メソッドを使用します。これらのクラス・メソッドの全引数のリストを、以下に順番に示します。
-
pSource、pStream、または pString — ソース・ドキュメント。
-
CreateFromFile() の場合は、この引数はファイル名です。
-
CreateFromStream() の場合は、この引数はバイナリ・ストリームです。
-
CreateFromString() の場合は、この引数は文字列です。
-
-
pDocument — 出力パラメータとして返される結果。これは、%XML.XPATH.DocumentOpens in a new tab のインスタンスです。
-
pResolver — ソースの解析時に使用される、オプションのエンティティ・リゾルバ。詳細は、"SAX パーサの使用法のカスタマイズ" の "カスタム・エンティティの解析実行" を参照してください。
-
pErrorHandler — オプションのカスタム・エラー・ハンドラ。次のトピックの "エラー処理のカスタマイズ" を参照してください。カスタム・エラー・ハンドラを指定しない場合は、メソッドは %XML.XSLT.ErrorHandlerOpens in a new tab の新しいインスタンスを使用します。
-
pFlags — SAX パーサによる検証と処理を制御するオプションのフラグ。詳細は、"SAX パーサの使用法のカスタマイズ" の "パーサ・フラグの設定" を参照してください。
-
pSchemaSpec — ドキュメント・ソースの検証の基準になる、オプションのスキーマ仕様。この引数は、ネームスペース/URL のペアをコンマで区切って指定したリストを含む文字列です。
"namespace URL,namespace URL"
ここで、namespace はスキーマに使用する XML ネームスペースで、URL はスキーマ・ドキュメントの位置を表す URL です。ネームスペースと URL の値の間は、1 つの空白文字で区切られています。
-
pPrefixMappings — オプションの接頭語のマッピング文字列。詳細は、サブセクション "既定のネームスペースの接頭語のマッピングの追加" を参照してください。
CreateFromFile()、CreateFromStream()、および CreateFromString() の各メソッドはステータスを返しますが、このステータスをチェックする必要があります。以下はその例です。
Set tSC=##class(%XML.XPATH.Document).CreateFromFile("c:\sample.xml",.tDocument)
If $$$ISERR(tSC) Do $System.OBJ.DisplayError(tSC)
既定のネームスペースの接頭語のマッピングの追加
XML ドキュメントで既定のネームスペースを使用すると、XPath に問題が発生します。以下の例を考えてみます。
<?xml version="1.0"?>
<staff xmlns="http://www.staff.org">
<doc type="consultant">
<name first="David" last="Marston">Mr. Marston</name>
<name first="David" last="Bertoni">Mr. Bertoni</name>
<name first="Donald" last="Leslie">Mr. Leslie</name>
<name first="Emily" last="Farmer">Ms. Farmer</name>
</doc>
</staff>
この場合、<staff> 要素はネームスペースに属しますが、ネームスペース接頭語は持ちません。XPath では <doc> 要素に簡単にアクセスすることができません。
既定のネームスペースがあるノードに簡単にアクセスできるように、%XML.XPATH.DocumentOpens in a new tab クラスでは、以下の 2 つの方法で使用できる接頭語のマッピング機能を提供しています。
-
%XML.XPATH.DocumentOpens in a new tab のインスタンスの PrefixMappings プロパティを設定できます。このプロパティは、XPath 式が完全なネームスペース URI ではなく接頭語を使用できるように、ソース・ドキュメント内のそれぞれの既定のネームスペースに一意の接頭語を提供することを目的としています。
PrefixMappings プロパティはコンマ区切りのリストで構成される文字列です。各リスト項目は、接頭語の後にスペース文字が 1 つ、その後にネームスペース URI の順で記述されます。
-
CreateFromFile()、CreateFromStream()、または CreateFromString() を呼び出すときには、pPrefixMappings 引数を指定できます。この文字列は前述の形式と同じである必要があります。
"XPATH ドキュメント作成時の引数リスト" を参照してください。
その後、他のネームスペースの接頭語を使用する場合と同じ方法で、これらの接頭語を使用します。
例えば、前述の XML を %XML.XPATH.DocumentOpens in a new tab のインスタンスに読み込む場合に、以下のように PrefixMappings を設定したとします。
"s http://www.staff.org"
この場合、"/s:staff/s:doc" を使用して <doc> 要素にアクセスできます。
インスタンス・メソッド GetPrefix() を使用することで、ドキュメントで指定されたパスに対して指定した接頭語を取得できます。
XPath 式の評価
XPath 式を評価するには、%XML.XPATH.DocumentOpens in a new tab のインスタンスの EvaluateExpression() メソッドを使用します。このメソッドでは、次の順序で以下の引数を指定します。
-
pContext — 式を評価するコンテキストを指定するノード・コンテキスト。その目的のノードへのパスの XPath 構文を含む文字列を指定します。以下はその例です。
"/staff/doc"
-
pExpression — 特定の結果を選択する述語。目的の XPath 構文を含む文字列を指定します。以下はその例です。
"name[@last='Marston']"
Note:他の技術では、述語をノード・パスの末尾に連結するのが一般的です。%XML.XPATH.DocumentOpens in a new tab クラスではこの構文をサポートしていません。これは、基本となる XSLT プロセッサは個別の引数としてノード・コンテキストと述語を必要とするためです。
-
pResults — 出力パラメータとして返される結果。結果の詳細は、"XPath の結果の使用法" を参照してください。
EvaluateExpression() メソッドではステータスが返されます。これはチェックする必要があります。以下はその例です。
Set tSC=tDoc.EvaluateExpression("/staff/doc","name[@last='Smith']",.tRes)
If $$$ISERR(tSC) {Do $System.OBJ.DisplayError(tSC)}
XPath の結果の使用法
XPath 式では、XML ドキュメントのサブツリー、複数のサブツリー、またはスカラ結果を返すことができます。%XML.XPATH.DocumentOpens in a new tab の EvaluateExpression() メソッドはこれらのすべてのケースを処理するように設計されています。具体的には、結果のリストを返します。リストの各項目には、以下の値のいずれかを持つ Type プロパティがあります。
-
$$$XPATHDOM — この項目に XML ドキュメントのサブツリーが含まれることを示します。この項目は、サブツリーをナビゲートおよび検証するためのメソッドを提供する %XML.XPATH.DOMResultOpens in a new tab のインスタンスです。詳細は、"XML サブツリーの検証" を参照してください。
-
$$$XPATHVALUE — この項目が単一のスカラ結果であることを示します。この項目は、%XML.XPATH.ValueResultOpens in a new tab のインスタンスです。詳細は、"スカラ結果の検証" を参照してください。
これらのマクロは、%occXSLT.inc インクルード・ファイルで定義されています。
以下のサブセクションでは、これらのクラスの詳細と、使用する可能性のある全般的アプローチの概要と例について説明します。
XML サブツリーの検証
このセクションでは、%XML.XPATH.DOMResultOpens in a new tab によって表される XML サブツリーのナビゲート方法と、そのサブツリーでの現在位置についての情報を取得する方法を説明します。
ノードのプロパティ
Type プロパティに加え、%XML.XPATH.DOMResultOpens in a new tab の以下のプロパティも現在位置についての情報を提供します。
現在のノードが要素の場合、このプロパティは、要素の属性の番号を示します。
リーダがソース・ドキュメントの末尾に到達した場合は True、それ以外の場合は False です。
現在のノードが要素の場合、その要素に属性があれば、このプロパティは True です (属性がなければ False です)。現在のノードが属性の場合、このプロパティは True です。
その他のタイプのノードでは、このプロパティは False になります。
現在のノードが値を持つタイプのノードの場合 (その値が Null であっても)、True です。それ以外の場合、このプロパティは False です。
attribute または element のタイプのノードの場合、これは現在の要素または属性の名前からネームスペースの接頭語を除いたものとなります。その他すべてのタイプのノードでは、このプロパティは Null になります。
ノードのタイプに応じた、現在のノードの完全修飾名です。
現在のノードのタイプであり、その値は、attribute、chars、cdata、comment、document、documentfragment、documenttype、element、entity、entityreference、notation、または processinginstruction のいずれかです。
要素のタイプのノードの場合、これは要素へのパスとなります。その他すべてのタイプのノードでは、このプロパティは Null になります。
全体の読み取り状態を示します。以下のいずれかの状態となります。
-
"initial" は、Read() メソッドがまだ呼び出されていないことを示します。
-
"cursoractive" は、Read() メソッドが少なくとも 1 回呼び出されたことを示します。
-
"eof" は、ファイルの末尾に達したことを示します。
現在のノードの URI。返される値は、ノードのタイプによって異なります。
ノードのタイプに応じた、現在のノードの値 (存在する場合) です。値のサイズが 32 KB より小さい場合、これは文字列です。それ以外の場合、文字ストリームです。詳細は、"スカラ結果の検証" を参照してください。
スカラ結果の検証
このセクションでは、%XML.XPATH.ValueResultOpens in a new tab クラスによって表される XPath 結果の使用法を説明します。このクラスは、Type プロパティ以外に Value プロパティも提供します。
値の長さが 32 KB より大きい場合、自動的にストリーム・オブジェクトに格納されることに注意してください。受け取る結果の種類が確実にわかっていない限り、Value がストリーム・オブジェクトであるかどうかを確認します。このためには、$IsObject 関数を使用できます (つまり、この値がオブジェクトの場合、それは、可能な唯一の種類のオブジェクトであるため、ストリーム・オブジェクトです)。
以下の部分は、テストの例を示しています。
// Value can be a stream if result is greater than 32 KB in length
Set tValue=tResult.Value
If $IsObject(tValue){
Write ! Do tValue.OutputToDevice()
} else {
Write tValue
}
一般的なアプローチ
XPath 式を評価するときに受け取る結果の種類が確実にわかっていない限り、最も一般的で可能性のあるケースを処理するためのコードを記述します。コードの構成例を以下に示します。
-
返される結果のリストにある要素の数を検索します。このリストの繰り返し処理を行います。
-
各リスト項目について、Type プロパティを確認します。
-
Type が $$$XPATHDOM の場合、%XML.XPATH.DOMResultOpens in a new tab クラスのメソッドを使用してこの XML サブツリーをナビゲートし、検証します。
-
Type が $$$XPATHVALUE の場合、Value プロパティがストリーム・オブジェクトかどうかを確認します。ストリーム・オブジェクトの場合は、通常のストリーム・インタフェースを使用してデータにアクセスします。それ以外の場合は、Value プロパティは文字列です。
-
使用例は、%XML.XPATH.DocumentOpens in a new tab の ExampleDisplayResults() クラス・メソッドを参照してください。このメソッドは、前のリストで説明した方法で結果を検証し、その後、結果をターミナルに書き込みます。以下のセクションでは、このメソッドからの出力形式を示します。
例
このセクションの例は、以下の XML ドキュメントに対して XPath 式を評価します。
<?xml version="1.0"?>
<staff>
<doc type="consultant">
<name first="David" last="Marston">Mr. Marston</name>
<name first="David" last="Bertoni">Mr. Bertoni</name>
<name first="Donald" last="Leslie">Mr. Leslie</name>
<name first="Emily" last="Farmer">Ms. Farmer</name>
</doc>
<doc type="GP">
<name first="Myriam" last="Midy">Ms. Midy</name>
<name first="Paul" last="Dick">Mr. Dick</name>
<name first="Scott" last="Boag">Mr. Boag</name>
<name first="Shane" last="Curcuru">Mr. Curcuru</name>
<name first="Joseph" last="Kesselman">Mr. Kesselman</name>
<name first="Stephen" last="Auriemma">Mr. Auriemma</name>
</doc>
</staff>
これらの例は、%XML.XPATH.DocumentOpens in a new tab クラスに含まれる大規模な例を変更したものです。詳細を確認するには、ソース・コードを参照してください。
サブツリー結果を持つ XPath 式の評価
以下のクラス・メソッドは XML ファイルを読み取り、XML サブツリーを返す XPath 式を評価します。
/// Evaluates an XPath expression that returns a DOM Result
ClassMethod Example1()
{
Set tSC=$$$OK
do {
Set tSC=##class(%XML.XPATH.Document).CreateFromFile(filename,.tDoc)
If $$$ISERR(tSC) {Do $System.OBJ.DisplayError(tSC) Quit}
Set context="/staff/doc"
Set expr="name[@last='Marston']"
Set tSC=tDoc.EvaluateExpression(context,expr,.tRes)
If $$$ISERR(tSC) Quit
Do ##class(%XML.XPATH.Document).ExampleDisplayResults(tRes)
} while (0)
If $$$ISERR(tSC) {Do $System.OBJ.DisplayError(tSC)}
Quit
}
この例では、last 属性が Marston である <name> 要素を持つすべてのノードが選択されます。この式は、<staff> 要素の <doc> ノードで評価されます。
この例は %XML.XPATH.DocumentOpens in a new tab の ExampleDisplayResults() クラス・メソッドを使用することに注意してください。
前述の XML ファイルを入力として指定して Example1() メソッドを実行すると、以下の出力が表示されます。
XPATH DOM
element: name
attribute: first Value: David
attribute: last Value: Marston
chars : #text Value: Mr. Marston
スカラ結果を持つ XPath 式の評価
以下のクラス・メソッドは XML ファイルを読み取り、スカラ結果を返す XPath 式を評価します。
/// Evaluates an XPath expression that returns a VALUE Result
ClassMethod Example2()
{
Set tSC=$$$OK
do {
Set tSC=##class(%XML.XPATH.Document).CreateFromFile(filename,.tDoc)
If $$$ISERR(tSC) {Do $System.OBJ.DisplayError(tSC) Quit}
Set tSC=tDoc.EvaluateExpression("/staff","count(doc)",.tRes)
If $$$ISERR(tSC) Quit
Do ##class(%XML.XPATH.Document).ExampleDisplayResults(tRes)
} while (0)
If $$$ISERR(tSC) {Do $System.OBJ.DisplayError(tSC)}
Quit
}
この例では、<doc> サブノードがカウントされます。この式は、<staff> 要素で評価されます。
前述の XML ファイルを入力として指定して Example2() メソッドを実行すると、以下の出力が表示されます。
XPATH VALUE
2