xml2
モジュールはXPath問い合わせとXSLT機能を提供します。
PostgreSQL 8.3から、SQL/XML標準に基づくXML関連の機能はコアサーバ内に存在します。
その機能は、XML構文検査、XPath問い合わせなど本モジュールが行なうことと同等のこととそれ以上のことを範囲としますが、APIには互換性はありません。
新しい標準APIのため、本モジュールは今後のバージョンのPostgreSQLで削除される予定ですので、アプリケーションの変換が推奨されています。
本モジュールの機能に新しいAPIに適用できないものがあることが分かった場合、その不足に取り組むことができるように<pgsql-hackers@postgresql.org>
にその問題を表明してください。
表 F.35に本モジュールで提供する関数を示します。
これらの関数は簡単なXML解析とXPath問い合わせを提供します。
すべての引数はtext
型です。
簡潔にするため説明しません。
表F.35 関数
関数 | 結果 | 説明 |
---|---|---|
xml_valid(document)
| bool
| これはパラメータとして与えられた文書テキストを解析し、文書が整形式のXMLであれば真を返します。
(注意:これは標準のPostgreSQL関数 |
xpath_string(document, query)
| text
| これらの関数は与えられた文書に対するXPath問い合わせを評価し、結果を指定した型にキャストします。 |
xpath_number(document, query)
| float4
| |
xpath_bool(document, query)
| bool
| |
xpath_nodeset(document, query, toptag, itemtag)
| text
| これは文書に対する問い合わせを評価し、XMLタグ内に結果を包みます。 結果が複数の値であれば、出力は以下のようになります。 <toptag> <itemtag>Value 1 which could be an XML fragment</itemtag> <itemtag>Value 2....</itemtag> </toptag>
|
xpath_nodeset(document, query)
| text
|
|
xpath_nodeset(document, query, itemtag)
| text
|
|
xpath_list(document, query, separator)
| text
| この関数は複数の値を指定した区切り文字で区切って返します。
例えば、区切り文字が |
xpath_list(document, query)
| text
| これは、, を区切り文字として使用する、上の関数のラッパです。
|
xpath_table
xpath_table(text key, text document, text relation, text xpaths, text criteria) returns setof record
xpath_table
は各文書集合に対するXPath問い合わせ集合を評価し、結果をテーブルとして返すテーブル関数です。
元文書テーブルの主キーフィールドが結果の第一列として返されますので、結果セットを容易に結合で使用することができます。
パラメータについては表 F.36で説明します。
表F.36 xpath_table
のパラメータ
パラメータ | 説明 |
---|---|
key | 「key」フィールドの名前です。 これは、出力テーブルの第一列として使用される単なるフィールドです。 つまり、これは各出力行の出現元を識別するレコードです。 (後述の複数値に関する注記を参照してください。) |
document | XML文書を含むフィールドの名前です。 |
relation | 文書を含むテーブルまたはビューの名前です。 |
xpaths |
|
criteria | WHERE句の内容です。
これは省略することができません。
リレーション内の全行を処理したい場合は |
(XPath文字列を除く)これらのパラメータは普通のSQL SELECT 文に単純に置換されます。 このため、多少の柔軟性があります。
SELECT <key>, <document> FROM <relation> WHERE <criteria>
文は上の通りですので、これらのパラメータにはそれぞれの場所で有効なものであれば何でもよいわけです。 このSELECTの結果は正確に2つの列を返さなければなりません(キーまたは文書に対して複数のフィールドを列挙させようとしない限りです)。 この簡略された手法では、SQLインジェクション攻撃を防ぐためにユーザから与えられた値をすべて検証しなければならないことに注意してください。
この関数は、出力列を指定するためのAS
句を付けたFROM
式内で使用されなければなりません。
以下に例を示します。
SELECT * FROM xpath_table('article_id', 'article_xml', 'articles', '/article/author|/article/pages|/article/title', 'date_entered > ''2003-01-01'' ') AS t(article_id integer, author text, page_count integer, title text);
このAS
句は、出力テーブルの列名とその型を定義します。
先頭が「key」フィールド、残りがXPath問い合わせに対応します。
結果列より多くのXPath問い合わせが存在する場合、余った問い合わせは無視されます。
XPath問い合わせより多くの結果列が存在する場合は余った列はNULLになります。
この例でpage_count
結果列が整数として定義されていることに注意してください。
関数は内部的に文字列表現で扱います。
このため、出力内で整数で扱いたいと言っている時、XPath結果の文字列表現を取り出し、整数(またはAS
句で要求した任意の型)に変換するためにPostgreSQLの入力関数を使用します。
例えば結果が空など、変換できない場合はエラーになります。
ですので、データに何らかの問題があると考えられる場合、列型としてtext
に限定する方がよいかもしれません。
SELECT
文の呼び出しでは、単なるSELECT *
でなければならない必要性はありません。
出力列を名前で参照することも他のテーブルと結合することも可能です。
この関数は希望の何らかの操作(例えば集約、結合、ソートなど)を行うことができる仮想テーブルを生成します。
このため以下をより複雑な例として示すことができます。
SELECT t.title, p.fullname, p.email FROM xpath_table('article_id', 'article_xml', 'articles', '/article/title|/article/author/@id', 'xpath_string(article_xml,''/article/@date'') > ''2003-03-20'' ') AS t(article_id integer, title text, author_id integer), tblPeopleInfo AS p WHERE t.author_id = p.person_id;
当然ながら、簡便にするためにこれをすべてビューとして包み隠すことができます。
xpath_table
関数は各XPath問い合わせの結果が複数の値を持つ可能性があることを前提としています。
このため、この関数が返す行数は入力文書の数と同じにならない可能性があります。
返される最初の行には各問い合わせの最初の結果が、2番目の行には各問い合わせの2番目の結果が含まれます。
問い合わせの1つが他よりも少ない値を持つ場合は代わりにNULL値が返されます。
指定したXPath問い合わせが単一の結果(おそらく一意な文書識別子)のみを返すことがユーザが分かっている場合があります。 もしこれを複数の結果を返すXPathと一緒に使用されると、単一値の結果は結果の最初の行にのみ現れます。 この解決方法はより単純なXPath問い合わせに対する結合部分としてキーフィールドを使用することです。 以下に例を示します。
CREATE TABLE test ( id int PRIMARY KEY, xml text ); INSERT INTO test VALUES (1, '<doc num="C1"> <line num="L1"><a>1</a><b>2</b><c>3</c></line> <line num="L2"><a>11</a><b>22</b><c>33</c></line> </doc>'); INSERT INTO test VALUES (2, '<doc num="C2"> <line num="L1"><a>111</a><b>222</b><c>333</c></line> <line num="L2"><a>111</a><b>222</b><c>333</c></line> </doc>'); SELECT * FROM xpath_table('id','xml','test', '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c', 'true') AS t(id int, doc_num varchar(10), line_num varchar(10), val1 int, val2 int, val3 int) WHERE id = 1 ORDER BY doc_num, line_num id | doc_num | line_num | val1 | val2 | val3 ----+---------+----------+------+------+------ 1 | C1 | L1 | 1 | 2 | 3 1 | | L2 | 11 | 22 | 33
各行にdoc_num
を付けるためには、2つのxpath_table
を呼び出し、その結果を結合することです。
SELECT t.*,i.doc_num FROM xpath_table('id', 'xml', 'test', '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c', 'true') AS t(id int, line_num varchar(10), val1 int, val2 int, val3 int), xpath_table('id', 'xml', 'test', '/doc/@num', 'true') AS i(id int, doc_num varchar(10)) WHERE i.id=t.id AND i.id=1 ORDER BY doc_num, line_num; id | line_num | val1 | val2 | val3 | doc_num ----+----------+------+------+------+--------- 1 | L1 | 1 | 2 | 3 | C1 1 | L2 | 11 | 22 | 33 | C1 (2 rows)
libxsltがインストールされている場合、以下の関数を使用することができます。
John Gray <jgray@azuli.co.uk>
本モジュールの開発はTorchbox Ltd. (www.torchbox.com)が後援しました。 PostgreSQLと同じBSDライセンスです。