XML函數(shù)
本節(jié)中描述的函數(shù)以及類函數(shù)的表達(dá)式都在類型xml
的值上操作。用于在值和類型xml
之間轉(zhuǎn)換的類函數(shù)的表達(dá)式xmlparse
和xmlserialize
記錄在這里,而不是在本節(jié)中。
使用大部分這些函數(shù)要求本數(shù)據(jù)庫(kù)使用了configure --with-libxml
進(jìn)行編譯。
產(chǎn)生XML內(nèi)容
有一組函數(shù)和類函數(shù)的表達(dá)式可以用來(lái)從SQL數(shù)據(jù)產(chǎn)生XML內(nèi)容。它們特別適合于將查詢結(jié)果格式化成XML文檔以便于在客戶端應(yīng)用中處理。
xmlcomment
xmlcomment ( text ) → xml
函數(shù)xmlcomment
創(chuàng)建了一個(gè)XML值,它包含一個(gè)使用指定文本作為內(nèi)容的XML注釋。 該文本不包含“--
”或者也不會(huì)以一個(gè)“-
”結(jié)尾,否則該結(jié)果的結(jié)構(gòu)不是一個(gè)合法的XML注釋。如果參數(shù)為空,結(jié)果也為空。
示例:
SELECT xmlcomment('hello');
xmlcomment
--------------
<!--hello-->
xmlconcat
xmlconcat ( xml [, ...] ) → xml
函數(shù)xmlconcat
將由單個(gè) XML 值組成的列表串接成一個(gè)單獨(dú)的值,這個(gè)值包含一個(gè)XML內(nèi)容片段。空值會(huì)被忽略,只有當(dāng)沒(méi)有參數(shù)為非空時(shí)結(jié)果才為空。
示例:
SELECT xmlconcat('<abc/>', '<bar>foo</bar>');
xmlconcat
----------------------
<abc/><bar>foo</bar>
如果XML聲明存在,它們會(huì)按照下面的方式被組合。如果所有的參數(shù)值都有相同的XML版本聲明,該版本將被用在結(jié)果中,否則將不使用版本。如果所有參數(shù)值有獨(dú)立聲明值“yes”,那么該值將被用在結(jié)果中。如果所有參數(shù)值都有一個(gè)獨(dú)立聲明值并且至少有一個(gè)為“no”,則“no”被用在結(jié)果中。否則結(jié)果中將沒(méi)有獨(dú)立聲明。如果結(jié)果被決定要求一個(gè)獨(dú)立聲明但是沒(méi)有版本聲明,將會(huì)使用一個(gè)版本 1.0 的版本聲明,因?yàn)閄ML要求一個(gè)XML聲明要包含一個(gè)版本聲明。編碼聲明會(huì)被忽略并且在所有情況中都會(huì)被移除。
示例:
SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');
xmlconcat
-----------------------------------
<?xml version="1.1"?><foo/><bar/>
xmlelement
xmlelement ( NAME name [, XMLATTRIBUTES ( attvalue [ AS attname ] [, ...] ) ] [, content [, ...]] ) → xml
表達(dá)式xmlelement
使用給定名稱、屬性和內(nèi)容產(chǎn)生一個(gè)XML元素。 語(yǔ)法中顯示的name
和attname
項(xiàng)是簡(jiǎn)單的標(biāo)識(shí)符,而不是值。 attvalue
和content
項(xiàng)是表達(dá)式,它們可以生成任何本數(shù)據(jù)庫(kù)數(shù)據(jù)類型。 XMLATTRIBUTES
的參數(shù)生成XML元素的屬性;將content
值連接起來(lái)形成其內(nèi)容。
示例:
SELECT xmlelement(name foo);
xmlelement
------------
<foo/>
SELECT xmlelement(name foo, xmlattributes('xyz' as bar));
xmlelement
------------------
<foo bar="xyz"/>
SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');
xmlelement
-------------------------------------
<foo bar="2007-01-26">content</foo>
不是合法XML名字的元素名和屬性名將被逃逸,逃逸的方法是將違反的字符用序列_x``HHHH``_
替換,其中HHHH
是被替換字符的Unicode代碼點(diǎn)的十六進(jìn)制表示。例如:
SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));
xmlelement
----------------------------------
<foo_x0024_bar a_x0026_b="xyz"/>
如果屬性值是一個(gè)列引用,則不需要指定一個(gè)顯式的屬性名,在這種情況下列的名字將被默認(rèn)用于屬性的名字。在其他情況下,屬性必須被給定一個(gè)顯式名稱。因此該示例是合法的:
CREATE TABLE test (a xml, b xml);
SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;
但是下面這些不合法:
SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;
如果指定了元素內(nèi)容,它們將被根據(jù)其數(shù)據(jù)類型格式化。如果內(nèi)容本身也是類型xml
,就可以構(gòu)建復(fù)雜的XML文檔。例如:
SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
xmlelement(name abc),
xmlcomment('test'),
xmlelement(name xyz));
xmlelement
----------------------------------------------
<foo bar="xyz"><abc/><!--test--><xyz/></foo>
其他類型的內(nèi)容將被格式化為合法的XML字符數(shù)據(jù)。這意味著字符 <, >
, 和&
將被轉(zhuǎn)換為實(shí)體。二進(jìn)制數(shù)據(jù)(數(shù)據(jù)類型bytea
)將被表示成base64或十六進(jìn)制編碼,具體取決于配置參數(shù)xmlbinary的設(shè)置。
xmlforest
xmlforest ( content [ AS name ] [, ...] ) → xml
表達(dá)式xmlforest
使用給定名稱和內(nèi)容產(chǎn)生一個(gè)元素的XML森林(序列)。 對(duì)于xmlelement
,每個(gè)name
都必須是一個(gè)簡(jiǎn)單的標(biāo)識(shí)符,而content
表達(dá)式可以有任何數(shù)據(jù)類型。
示例:
SELECT xmlforest('abc' AS foo, 123 AS bar);
xmlforest
------------------------------
<foo>abc</foo><bar>123</bar>
SELECT xmlforest(table_name, column_name)
FROM information_schema.columns
WHERE table_schema = 'pg_catalog';
xmlforest
------------------------------------?-----------------------------------
<table_name>pg_authid</table_name>?<column_name>rolname</column_name>
<table_name>pg_authid</table_name>?<column_name>rolsuper</column_name>
...
如我們?cè)诘诙€(gè)示例中所見(jiàn),如果內(nèi)容值是一個(gè)列引用,元素名稱可以被忽略,這種情況下默認(rèn)使用列名。否則,必須指定一個(gè)名字。
如上文xmlelement
所示,非法XML名字的元素名會(huì)被逃逸。相似地,內(nèi)容數(shù)據(jù)也會(huì)被逃逸來(lái)產(chǎn)生合法的XML內(nèi)容,除非它已經(jīng)是一個(gè)xml
類型。
如果XML森林由多于一個(gè)元素組成,那么它不是合法的XML文檔,因此在xmlelement
中包裝xmlforest
表達(dá)式會(huì)有用處。
xmlpi
xmlpi ( NAME name [, content ] ) → xml
表達(dá)式xmlpi
創(chuàng)建一個(gè)XML處理指令。 對(duì)于xmlelement
,name
必須是一個(gè)簡(jiǎn)單的標(biāo)識(shí)符,而content
表達(dá)式可以有任何數(shù)據(jù)類型。如果存在,content
不能包含字符序列?>
。
示例:
SELECT xmlpi(name php, 'echo "hello world";');
xmlpi
-----------------------------
<?php echo "hello world";?>
xmlroot
xmlroot ( xml, VERSION {text|NO VALUE} [, STANDALONE {YES|NO|NO VALUE} ] ) → xml
表達(dá)式xmlroot
修改一個(gè)XML值的根節(jié)點(diǎn)的屬性。如果指定了一個(gè)版本,它會(huì)替換根節(jié)點(diǎn)的版本聲明中的值;如果指定了一個(gè)獨(dú)立設(shè)置,它會(huì)替換根節(jié)點(diǎn)的獨(dú)立聲明中的值。
SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'),
version '1.0', standalone yes);
xmlroot
----------------------------------------
<?xml version="1.0" standalone="yes"?>
<content>abc</content>
xmlagg
xmlagg ( xml ) → xml
和這里描述的其他函數(shù)不同,函數(shù)xmlagg
是一個(gè)聚集函數(shù)。它將聚集函數(shù)調(diào)用的輸入值串接起來(lái),非常像xmlconcat
所做的事情,除了串接是跨行發(fā)生的而不是在單一行的多個(gè)表達(dá)式上發(fā)生。
示例:
CREATE TABLE test (y int, x xml);
INSERT INTO test VALUES (1, '<foo>abc</foo>');
INSERT INTO test VALUES (2, '<bar/>');
SELECT xmlagg(x) FROM test;
xmlagg
----------------------
<foo>abc</foo><bar/>
為了決定串接的順序,可以為聚集調(diào)用增加一個(gè)ORDER BY
子句。例如:
SELECT xmlagg(x ORDER BY y DESC) FROM test;
xmlagg
----------------------
<bar/><foo>abc</foo>
推薦在以前的版本中使用下列非標(biāo)準(zhǔn)方法,并且它們?cè)谔囟ㄇ闆r下仍然有用:
SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;
xmlagg
----------------------
<bar/><foo>abc</foo>
XML謂詞
這一節(jié)描述的表達(dá)式檢查xml
值的屬性。
IS DOCUMENT
xml IS DOCUMENT → boolean
如果參數(shù)XML值是一個(gè)正確的XML文檔,則IS DOCUMENT
返回真,如果不是則返回假(即它是一個(gè)內(nèi)容片段),或者是參數(shù)為空時(shí)返回空。
IS NOT DOCUMENT
xml IS NOT DOCUMENT → boolean
如果參數(shù)中的XML值是一個(gè)正確的XML文檔,那么表達(dá)式IS NOT DOCUMENT
返回假,否則返回真(也就是說(shuō)它是一個(gè)內(nèi)容片段),如果參數(shù)為空則返回空。
XMLEXISTS
XMLEXISTS ( text PASSING [BY {REF|VALUE}] xml [BY {REF|VALUE}] ) → boolean
函數(shù)xmlexists
評(píng)價(jià)一個(gè)XPath 1.0表達(dá)式(第一個(gè)參數(shù)),以傳遞的XML值作為其上下文項(xiàng)。 如果評(píng)價(jià)的結(jié)果產(chǎn)生一個(gè)空節(jié)點(diǎn)集,該函數(shù)返回false,如果產(chǎn)生任何其他值,則返回true。 如果任何參數(shù)為空,則函數(shù)返回null。 作為上下文項(xiàng)傳遞的非空值必須是一個(gè)XML文檔,而不是內(nèi)容片段或任何非XML值。
示例:
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY VALUE '<towns><town>Toronto</town><town>Ottawa</town></towns>');
xmlexists
------------
t
(1 row)
在SQL標(biāo)準(zhǔn)中,xmlexists
函數(shù)評(píng)估XML查詢語(yǔ)言中的表達(dá)式,但本數(shù)據(jù)庫(kù)只允許使用XPath 1.0表達(dá)式。
xml_is_well_formed
xml_is_well_formed ( text ) → boolean
xml_is_well_formed_document ( text ) → boolean
xml_is_well_formed_content ( text ) → boolean
這些函數(shù)檢查一個(gè)text
串是不是一個(gè)良構(gòu)的XML,返回一個(gè)布爾結(jié)果。xml_is_well_formed_document
檢查一個(gè)良構(gòu)的文檔,而xml_is_well_formed_content
檢查良構(gòu)的內(nèi)容。如果xmloption配置參數(shù)被設(shè)置為DOCUMENT
,xml_is_well_formed
會(huì)做第一個(gè)函數(shù)的工作;如果配置參數(shù)被設(shè)置為CONTENT
,xml_is_well_formed
會(huì)做第二個(gè)函數(shù)的工作。這意味著xml_is_well_formed
對(duì)于檢查一個(gè)到類型xml
的簡(jiǎn)單造型是否會(huì)成功非常有用,而其他兩個(gè)函數(shù)對(duì)于檢查XMLPARSE
的對(duì)應(yīng)變體是否會(huì)成功有用。
示例:
SET xmloption TO DOCUMENT;
SELECT xml_is_well_formed('<>');
xml_is_well_formed
--------------------
f
(1 row)
SELECT xml_is_well_formed('<abc/>');
xml_is_well_formed
--------------------
t
(1 row)
SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
xml_is_well_formed
--------------------
t
(1 row)
SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>');
xml_is_well_formed_document
-----------------------------
t
(1 row)
SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>');
xml_is_well_formed_document
-----------------------------
f
(1 row)
最后一個(gè)示例顯示了這些檢查也包括名字空間是否正確地匹配。
處理 XML
要處理數(shù)據(jù)類型xml
的值, PostgreSQL提供了函數(shù)xpath
和xpath_exists
,它們計(jì)算XPath 1.0表達(dá)式以及XMLTABLE
表函數(shù)。
xpath
xpath ( xpath text, xml xml [, nsarray text[] ] ) → xml[]
函數(shù)xpath
根據(jù) XML 值xml
計(jì)算 XPath 1.0 表達(dá)式xpath
(以文本形式給出)。 它返回一個(gè)XML值的數(shù)組,該數(shù)組對(duì)應(yīng)于該XPath表達(dá)式產(chǎn)生的節(jié)點(diǎn)集合。 如果該XPath表達(dá)式返回一個(gè)標(biāo)量值而不是一個(gè)節(jié)點(diǎn)集合,將會(huì)返回一個(gè)單一元素的數(shù)組。
第二個(gè)參數(shù)必須是一個(gè)良構(gòu)的XML文檔。特殊地,它必須有一個(gè)單一根節(jié)點(diǎn)元素。
該函數(shù)可選的第三個(gè)參數(shù)是一個(gè)名字空間映射的數(shù)組。這個(gè)數(shù)組應(yīng)該是一個(gè)二維text
數(shù)組,其第二軸長(zhǎng)度等于 2(即它應(yīng)該是一個(gè)數(shù)組的數(shù)組,其中每一個(gè)都由剛好 2 個(gè)元素組成)。每個(gè)數(shù)組項(xiàng)的第一個(gè)元素是名字空間的名稱(別名),第二個(gè)元素是名字空間的 URI。并不要求在這個(gè)數(shù)組中提供的別名和在XML文檔本身中使用的那些名字空間相同(換句話說(shuō),在XML文檔中和在xpath
函數(shù)環(huán)境中,別名都是本地的)。
示例:
SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
ARRAY[ARRAY['my', 'http://example.com']]);
xpath
--------
{test}
(1 row)
要處理默認(rèn)(匿名)命名空間,做這樣的事情:
SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a>',
ARRAY[ARRAY['mydefns', 'http://example.com']]);
xpath
--------
{test}
(1 row)
xpath_exists
xpath_exists ( xpath text, xml xml [, nsarray text[] ] ) → boolean
函數(shù)xpath_exists
是xpath
函數(shù)的一種特殊形式。這個(gè)函數(shù)不是返回滿足XPath 1.0表達(dá)式的單一XML值,它返回一個(gè)布爾值表示查詢是否被滿足(具體來(lái)說(shuō),它是否產(chǎn)生了空節(jié)點(diǎn)集以外的任何值)。這個(gè)函數(shù)等價(jià)于標(biāo)準(zhǔn)的XMLEXISTS
謂詞,不過(guò)它還提供了對(duì)一個(gè)名字空間映射參數(shù)的支持。
示例:
SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
ARRAY[ARRAY['my', 'http://example.com']]);
xpath_exists
--------------
t
(1 row)
xmltable
XMLTABLE (
[ XMLNAMESPACES ( namespace_uri AS namespace_name [, ...] ), ]
row_expression PASSING [BY {REF|VALUE}] document_expression [BY {REF|VALUE}]
COLUMNS name { type [PATH column_expression] [DEFAULT default_expression] [NOT NULL | NULL]
| FOR ORDINALITY }
[, ...]
) → setof record
xmltable
表達(dá)式基于給定的XML值產(chǎn)生一個(gè)表、一個(gè)抽取行的XPath過(guò)濾器以及一個(gè)列定義集合。 雖然它在語(yǔ)法上類似于函數(shù),但它只能作為一個(gè)表出現(xiàn)在查詢的FROM
子句中。
可選的XMLNAMESPACES
子句是一個(gè)逗號(hào)分隔的名字空間定義列表。 其中每個(gè)namespace_uri
是一個(gè)text
表達(dá)式,每個(gè)namespace_name
是一個(gè)簡(jiǎn)單的標(biāo)識(shí)符。 它指定文檔中使用的XML名字空間及其別名。當(dāng)前不支持默認(rèn)的名字空間說(shuō)明。
所需的row_expression
參數(shù)是一個(gè)求值的XPath 1.0表達(dá)式(以text
形式給出),通過(guò)傳遞XML值document_expression
作為其上下文項(xiàng),得到一組XML節(jié)點(diǎn)。 這些節(jié)點(diǎn)就是xmltable
轉(zhuǎn)換為輸出行的內(nèi)容。如果document_expression
為空,或者row_expression
產(chǎn)生空節(jié)點(diǎn)集或節(jié)點(diǎn)集以外的任何值,則不會(huì)產(chǎn)生行。
document_expression
提供了上下文。row_expression
的項(xiàng)。 它必須是一個(gè)格式良好的XML文檔;不接受片段/森林。BY REF
和BY VALUE
子句如上文所討論的那樣,被接受但被忽略了。
在SQL標(biāo)準(zhǔn)中,xmltable
函數(shù)評(píng)估XML查詢語(yǔ)言中的表達(dá)式。 但本數(shù)據(jù)庫(kù)只允許使用XPath 1.0的表達(dá)式。
需要的COLUMNS
子句指定將在輸出表中生成的列。有關(guān)格式,請(qǐng)參閱上面的語(yǔ)法摘要。 每個(gè)列都需要一個(gè)名稱,作為一個(gè)數(shù)據(jù)類型(除非指定了 FOR ORDINALITY
,在這種情況下類型 integer
是隱式的)。 路徑、默認(rèn)值以及為空型子句是可選的。
被標(biāo)記為FOR ORDINALITY
的列將按照從row_expression
的結(jié)果節(jié)點(diǎn)集中檢索到的節(jié)點(diǎn)的順序,從1開(kāi)始,填充行號(hào)。最多只能有一個(gè)列被標(biāo)記為FOR ORDINALITY
。
XPath 1.0并沒(méi)有為節(jié)點(diǎn)集中的節(jié)點(diǎn)指定順序,因此依賴特定結(jié)果順序的代碼將取決于實(shí)現(xiàn)。
列的column_expression
是一個(gè)XPath 1.0表達(dá)式,它對(duì)每一行都要進(jìn)行求值,并以row_expression
結(jié)果中的當(dāng)前節(jié)點(diǎn)作為其上下文項(xiàng),以找到列的值。 如果沒(méi)有給出column_expression
,那么列名被用作隱式路徑。
如果一個(gè)列的XPath表達(dá)式返回一個(gè)非XML值(在XPath 1.0中僅限于string、boolean或double),而該列的PostgreSQL類型不是xml
,那么該列將被設(shè)置為將值的字符串表示法分配給PostgreSQL類型。 (如果值是布爾值,如果輸出列的類型類別是數(shù)字,那么它的字符串表示方式將被認(rèn)為是1
或0
,否則true
或false
)。
如果一個(gè)列的XPath表達(dá)式返回一個(gè)非空的XML節(jié)點(diǎn)集,并且該列的PostgreSQL類型是xml
,那么如果該列是文檔或內(nèi)容形式的,那么該列將被精確地分配表達(dá)式結(jié)果。 [7]
分配給xml
輸出列的非XML結(jié)果會(huì)產(chǎn)生內(nèi)容,一個(gè)帶有結(jié)果字符串值的單個(gè)文本節(jié)點(diǎn)。分配給任何其他類型的列的XML結(jié)果不能有一個(gè)以上的節(jié)點(diǎn),否則會(huì)產(chǎn)生錯(cuò)誤。如果正好有一個(gè)節(jié)點(diǎn),則該列將被設(shè)置為將該節(jié)點(diǎn)的字符串值(如XPath 1.0 string
函數(shù)定義的那樣)分配給PostgreSQL類型。
一個(gè)XML元素的字符串值是字符串值的協(xié)整,按文檔的順序。該元素中包含的所有文本節(jié)點(diǎn)及其子節(jié)點(diǎn)。字符串元素的值是一個(gè)沒(méi)有下級(jí)文本節(jié)點(diǎn)的元素的值是一個(gè)空字符串(不是NULL
)。任何xsi:nil
屬性都會(huì)被忽略。請(qǐng)注意,兩個(gè)非文本之間的text()
節(jié)點(diǎn)只用空格,而兩個(gè)非文本元素,并且保留了text()
上的前導(dǎo)白格。節(jié)點(diǎn)不被扁平化。XPath 1.0中的string
函數(shù)可以參考XPath 1.0中的定義其他XML節(jié)點(diǎn)類型和非XML值的字符串值的規(guī)則。
如果路徑表達(dá)式為給定行返回一個(gè)空節(jié)點(diǎn)集(通常情況下,當(dāng)它不匹配時(shí)),該列將被設(shè)置為NULL
,除非指定了default_expression
;然后使用評(píng)價(jià)該表達(dá)式產(chǎn)生的值。
default_expression
,而不是在調(diào)用xmltable
時(shí)立即被評(píng)價(jià),而是在每次需要列的默認(rèn)值時(shí),都會(huì)被評(píng)價(jià)。 如果表達(dá)式符合穩(wěn)定或不可更改的條件,則可以跳過(guò)重復(fù)評(píng)價(jià)。 這意味著,你可以在default_expression
中使用像nextval
這樣的不穩(wěn)定函數(shù)。
列可能會(huì)被標(biāo)記為NOT NULL
。如果一個(gè)NOT NULL
列的column_expression
不匹配任何東西并且沒(méi)有DEFAULT
或者default_expression
也計(jì)算為空,則會(huì)報(bào)告一個(gè)錯(cuò)誤。
示例:
CREATE TABLE xmldata AS SELECT
xml $$
<ROWS>
<ROW id="1">
<COUNTRY_ID>AU</COUNTRY_ID>
<COUNTRY_NAME>America</COUNTRY_NAME>
</ROW>
<ROW id="5">
<COUNTRY_ID>JP</COUNTRY_ID>
<COUNTRY_NAME>Japan</COUNTRY_NAME>
<PREMIER_NAME>Shinzo Abe</PREMIER_NAME>
<SIZE unit="sq_mi">145935</SIZE>
</ROW>
<ROW id="6">
<COUNTRY_ID>SG</COUNTRY_ID>
<COUNTRY_NAME>Singapore</COUNTRY_NAME>
<SIZE unit="sq_km">697</SIZE>
</ROW>
</ROWS>
$$ AS data;
SELECT xmltable.*
FROM xmldata,
XMLTABLE('//ROWS/ROW'
PASSING data
COLUMNS id int PATH '@id',
ordinality FOR ORDINALITY,
"COUNTRY_NAME" text,
country_id text PATH 'COUNTRY_ID',
size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
size_other text PATH
'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
id | ordinality | COUNTRY_NAME | country_id | size_sq_km | size_other | premier_name
----+------------+--------------+------------+------------+--------------+---------------
1 | 1 | America | US | | | not specified
5 | 2 | Japan | JP | | 145935 sq_mi | Shinzo Abe
6 | 3 | Singapore | SG | 697 | | not specified
接下來(lái)的示例展示了多個(gè)text()
節(jié)點(diǎn)的串接、列名用作XPath過(guò)濾器的用法以及對(duì)空格、XML注釋和處理指令的處理:
CREATE TABLE xmlelements AS SELECT
xml $$
<root>
<element> Hello<!-- xyxxz -->2a2<?aaaaa?> <!--x--> bbb<x>xxx</x>CC </element>
</root>
$$ AS data;
SELECT xmltable.*
FROM xmlelements, XMLTABLE('/root' PASSING data COLUMNS element text);
element
-------------------------
Hello2a2 bbbxxxCC
下面的示例展示了如何使用XMLNAMESPACES
子句指定用在XML文檔以及XPath表達(dá)式中的名字空間列表:
WITH xmldata(data) AS (VALUES ('
<example xmlns="http://example.com/myns" xmlns:B="http://example.com/b">
<item foo="1" B:bar="2"/>
<item foo="3" B:bar="4"/>
<item foo="4" B:bar="5"/>
</example>'::xml)
)
SELECT xmltable.*
FROM XMLTABLE(XMLNAMESPACES('http://example.com/myns' AS x,
'http://example.com/b' AS "B"),
'/x:example/x:item'
PASSING (SELECT data FROM xmldata)
COLUMNS foo int PATH '@foo',
bar int PATH '@B:bar');
foo | bar
-----+-----
1 | 2
3 | 4
4 | 5
(3 rows)
將表映射到XML
下面的函數(shù)將會(huì)把關(guān)系表的內(nèi)容映射成XML值。它們可以被看成是XML導(dǎo)出功能:
table_to_xml ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xml ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
cursor_to_xml ( cursor refcursor, count integer, nulls boolean,
tableforest boolean, targetns text ) → xml
table_to_xml
映射由參數(shù)table
傳遞的命名表的內(nèi)容。regclass
類型接受使用常見(jiàn)標(biāo)記標(biāo)識(shí)表的字符串,包括可選的模式限定和雙引號(hào)。query_to_xml
執(zhí)行由參數(shù)query
傳遞的查詢并且映射結(jié)果集。cursor_to_xml
從cursor
指定的游標(biāo)中取出指定數(shù)量的行。如果需要映射一個(gè)大型的表,我們推薦這種變體,因?yàn)槊恳粋€(gè)函數(shù)都是在內(nèi)存中構(gòu)建結(jié)果值的。
如果tableforest
為假,則結(jié)果的XML文檔看起來(lái)如下:
<tablename>
<row>
<columnname1>data</columnname1>
<columnname2>data</columnname2>
</row>
<row>
...
</row>
...
</tablename>
如果tableforest
為真,結(jié)果是一個(gè)看起來(lái)像這樣的XML內(nèi)容片段:
<tablename>
<columnname1>data</columnname1>
<columnname2>data</columnname2>
</tablename>
<tablename>
...
</tablename>
...
如果沒(méi)有表名可用,在映射一個(gè)查詢或一個(gè)游標(biāo)時(shí),在第一種格式中使用串table
,在第二種格式中使用row
。
這幾種格式的選擇由用戶決定。第一種格式是一個(gè)正確的XML文檔,它在很多應(yīng)用中都很重要。如果結(jié)果值要被重組為一個(gè)文檔,第二種格式在cursor_to_xml
函數(shù)中更有用。前文討論的產(chǎn)生XML內(nèi)容的函數(shù)(特別是xmlelement
)可以被用來(lái)把結(jié)果修改成符合用戶的要求。
數(shù)據(jù)值會(huì)被以前文的函數(shù)xmlelement
中描述的相同方法映射。
參數(shù)nulls
決定空值是否會(huì)被包含在輸出中。如果為真,列中的空值被表示為:
<columnname xsi:nil="true"/>
其中xsi
是XML模式實(shí)例的XML名字空間前綴。一個(gè)合適的名字空間聲明將被加入到結(jié)果值中。如果為假,包含空值的列將被從輸出中忽略掉。
參數(shù)targetns
指定想要的結(jié)果的XML名字空間。如果沒(méi)有想要的特定名字空間,將會(huì)傳遞一個(gè)空串。
下面的函數(shù)返回XML模式文檔,這些文檔描述上述對(duì)應(yīng)函數(shù)所執(zhí)行的映射:
table_to_xmlschema ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xmlschema ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
cursor_to_xmlschema ( cursor refcursor, nulls boolean,
tableforest boolean, targetns text ) → xml
最重要的是相同的參數(shù)被傳遞來(lái)獲得匹配的XML數(shù)據(jù)映射和XML模式文檔。
下面的函數(shù)產(chǎn)生XML數(shù)據(jù)映射和對(duì)應(yīng)的XML模式,并把產(chǎn)生的結(jié)果鏈接在一起放在一個(gè)文檔(或森林)中。在要求自包含和自描述的結(jié)果是它們非常有用:
table_to_xml_and_xmlschema ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xml_and_xmlschema ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
另外,下面的函數(shù)可用于產(chǎn)生相似的整個(gè)模式或整個(gè)當(dāng)前數(shù)據(jù)庫(kù)的映射:
schema_to_xml ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
schema_to_xmlschema ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
schema_to_xml_and_xmlschema ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xml ( nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xmlschema ( nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xml_and_xmlschema ( nulls boolean,
tableforest boolean, targetns text ) → xml
這些函數(shù)會(huì)忽略當(dāng)前用戶不可讀的表。數(shù)據(jù)庫(kù)范圍的函數(shù)還會(huì)忽略當(dāng)前用戶沒(méi)有USAGE
(查找)權(quán)限的模式。
請(qǐng)注意,這可能會(huì)產(chǎn)生大量數(shù)據(jù),這些數(shù)據(jù)需要在內(nèi)存中構(gòu)建。 當(dāng)請(qǐng)求大型模式或數(shù)據(jù)庫(kù)的內(nèi)容映射時(shí),可能值得考慮單獨(dú)映射表,甚至可能通過(guò)游標(biāo)。
一個(gè)模式內(nèi)容映射的結(jié)果看起來(lái)像這樣:
<schemaname>
table1-mapping
table2-mapping
...
</schemaname>
其中一個(gè)表映射的格式取決于上文解釋的tableforest
參數(shù)。
一個(gè)數(shù)據(jù)庫(kù)內(nèi)容映射的結(jié)果看起來(lái)像這樣:
<dbname>
<schema1name>
...
</schema1name>
<schema2name>
...
</schema2name>
...
</dbname>
其中的模式映射如上所述。
作為一個(gè)使用這些函數(shù)產(chǎn)生的輸出的示例,轉(zhuǎn)換SQL/XML輸出到HTML的XSLT樣式表展示了一個(gè)XSLT樣式表,它將table_to_xml_and_xmlschema
的輸出轉(zhuǎn)換為一個(gè)包含表數(shù)據(jù)的扁平轉(zhuǎn)印的HTML文檔。以一種相似的方式,這些函數(shù)的結(jié)果可以被轉(zhuǎn)換成其他基于XML的格式。
轉(zhuǎn)換SQL/XML輸出到HTML的XSLT樣式表**
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/1999/xhtml"
>
<xsl:output method="xml"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="schema" select="http://xsd:schema"/>
<xsl:variable name="tabletypename"
select="$schema/xsd:element[@name=name(current())]/@type"/>
<xsl:variable name="rowtypename"
select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
<html>
<head>
<title><xsl:value-of select="name(current())"/></title>
</head>
<body>
<table>
<tr>
<xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
<th><xsl:value-of select="."/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="row">
<tr>
<xsl:for-each select="*">
<td><xsl:value-of select="."/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
在頂層包含一個(gè)以上的元素節(jié)點(diǎn)的結(jié)果,或者在元素之外的非空格文本,就是內(nèi)容形式的一個(gè)示例。一個(gè)XPath結(jié)果可以是這兩種形式的,例如,如果它返回的是一個(gè)從包含它的元素中選擇的屬性節(jié)點(diǎn)。這樣的結(jié)果將被放到內(nèi)容形式中,每個(gè)不允許的節(jié)點(diǎn)都會(huì)被替換為它的字符串值,就像XPath 1.0string
函數(shù)定義的那樣。
XMLSERIALIZE
描述
該函數(shù)用于創(chuàng)建一個(gè)字符串或者包含value_expr
內(nèi)容的LOB
。
如果指定DOCUMENT,則value_expr必須是有效的XML文檔。
如果指定CONTENT,則value_expr不必是單根XML文檔。但是,它必須是有效的XML內(nèi)容。
指定的數(shù)據(jù)類型可以是字符串類型(VARCHAR2或VARCHAR,但不能是NVARCHAR或NVARCHAR2)或CLOB。默認(rèn)值為CLOB。
語(yǔ)法
XMLSERIALIZE({DOCUMENT|CEONTENT} value_expr [AS DATATYPE])
參數(shù)
參數(shù) | 說(shuō)明 |
{DOCUMENT|CEONTENT} | 用于指定 |
value_expr | 輸入?yún)?shù)表達(dá)式。 |
[AS DATATYPE] | 可選項(xiàng),用于指定輸入?yún)?shù)表達(dá)式轉(zhuǎn)換為何種類型。 |
返回類型
返回字符串類型數(shù)據(jù)或者LOB
類型數(shù)據(jù)。
示例
SELECT xmlserialize(content 'good' as char(10)) FROM DUAL;
xmlserialize
--------------
good
XMLROOT
描述
該函數(shù)允許通過(guò)在現(xiàn)有XML值和XML根信息中提供的版本和獨(dú)立屬性來(lái)創(chuàng)建新的XML值。
如果value_expr
已經(jīng)有prolog,則數(shù)據(jù)庫(kù)將返回一個(gè)錯(cuò)誤。如果輸入為null,則函數(shù)返回null。
第一個(gè)值
_expr
指定要為其提供prolog信息的XML值。在
VERSION
子句中,value_expr
必須解析為表示有效的XML版本的字符串。如果為VERSION
指定“NO VALUE”
,則版本默認(rèn)為1.0。如果省略了可選的
STANDALONE
子句,或者使用NO VALUE
指定它,則函數(shù)返回的值中沒(méi)有獨(dú)立屬性。
語(yǔ)法
XMLROOT(value_expr, VERSION {value_expr | NO VALUE} [, STANDALONE {YES | NO | NO VALUE}])
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
value_expr | 參數(shù)表達(dá)式。 |
VERSION {value_expr | NO VALUE} | 指定版本,如果指定 |
STANDALONE {YES | NO | NO VALUE} | 可選項(xiàng),如果不指定或者指定為 |
返回類型
返回<?xml version = "version" \[ STANDALONE = "{yes | no}" \]?>
格式的XML類型數(shù)據(jù)。
示例
SELECT xmlroot(xml '<foo/>', version no value, standalone yes) FROM DUAL;
xmlroot
----------------------------------------------
<?xml version="1.0" standalone="yes"?><foo/>
XMLPI
描述
該函數(shù)用標(biāo)識(shí)符和可選的value_expr
的評(píng)估結(jié)果生成XML處理指令。處理指令通常用于向應(yīng)用程序提供與XML文檔的全部或部分相關(guān)聯(lián)的信息。應(yīng)用程序使用處理指令來(lái)確定如何最好地處理XML文檔。
XMLPI受以下限制:
標(biāo)識(shí)符必須是處理指令的有效目標(biāo)。
在任何情況下都不能為標(biāo)識(shí)符指定xml組合。
標(biāo)識(shí)符不能包含連續(xù)字符
?>
。
語(yǔ)法
XMLPI([NAME] identifier[, value_expr])
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
value_expr | 參數(shù)表達(dá)式,必須解析為字符串。 |
返回類型
返回XML類型數(shù)據(jù)。
示例
SELECT xmlpi(name "xml-stylesheet", 'href="mystyle.css" type="text/css"');
xmlpi
-------------------------------------------------------
<?xml-stylesheet href="mystyle.css" type="text/css"?>
XMLPARSE
描述
該函數(shù)根據(jù)value_expr
的計(jì)算結(jié)果解析并生成一個(gè)XML
實(shí)例。value_expr
必須解析為字符串。如果value_expr
解析為null
,則函數(shù)返回null
。
語(yǔ)法
XMLPARSE({DOCUMENT|CONTENT}, value_expr[, WELLFORMED])
參數(shù)
參數(shù) | 說(shuō)明 |
DOCUMENT | 可選項(xiàng),選 |
CONTENT | 可選項(xiàng),選 |
value_expr | 參數(shù)表達(dá)式。 |
WELLFORMED | 可選項(xiàng),當(dāng)指定WELLFORMED時(shí),因?yàn)橹付ㄟ@個(gè)變量是保證value_expr解析為格式正確的XML文檔,因此此時(shí)數(shù)據(jù)庫(kù)不會(huì)執(zhí)行有效性檢查以確保輸入格式正確。 |
返回類型
返回XML
實(shí)例。
示例
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>');
xmlparse
-----------------------------------------------------------------------
<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>
XMLFOREST
描述
該函數(shù)用于將其每個(gè)參數(shù)轉(zhuǎn)換為XML,然后返回一個(gè)XML片段,該片段是這些轉(zhuǎn)換后的參數(shù)的串聯(lián)。
如果
value_expr
是標(biāo)量表達(dá)式,則可以省略AS
子句,而Oracle數(shù)據(jù)庫(kù)使用列名作為元素名稱。如果
value_expr
是對(duì)象類型或集合,則AS
子句是必需的,并且Oracle使用指定的c_alias
作為封閉標(biāo)記。別名(_alias)
最多可以包含4000個(gè)字符。如果
value_expr
為 null,則不會(huì)為該value_exper
創(chuàng)建任何元素。
語(yǔ)法
XMLFOREST(value_expr [AS c_alias] [, value_expr [AS c_alias], ...])
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
value_expr | 參數(shù)表達(dá)式。 |
c_alias | 可選項(xiàng),別名,在 |
返回類型
返回XML類型的串聯(lián)。
示例
CREATE TABLE testxmlschema.test3
AS SELECT true c1,
true::testboolxmldomain c2,
'2013-02-21'::date c3,
'2013-02-21'::testdatexmldomain c4;
SELECT xmlforest(c1, c2, c3, c4) FROM testxmlschema.test3;
xmlforest
------------------------------------------------------------------
<c1>true</c1><c2>true</c2><c3>2013-02-21</c3><c4>2013-02-21</c4>
XMLCONCAT
描述
XMLConcat將一系列XMLType實(shí)例作為輸入,連接每行的一系列元素,并返回連接的系列。XMLConcat與XMLSequence相反。
null表達(dá)式將從結(jié)果中刪除。如果所有的值表達(dá)式都為null,那么函數(shù)將返回null。
語(yǔ)法
XMLCONCAT(XMLType_instance[, XMLType_instance, ...])
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
XMLType_instance | 用于指定XMLType的示例。 |
返回類型
返回連接的XMLType實(shí)例的系列。
示例
SELECT xmlconcat('hello', 'you') FROM DUAL;
xmlconcat
-----------
helloyou
EXTRACTVALUE
描述
該函數(shù)將XMLType實(shí)例和XPath表達(dá)式作為參數(shù),并返回結(jié)果節(jié)點(diǎn)的標(biāo)量值。結(jié)果必須是單個(gè)節(jié)點(diǎn),并且必須是文本節(jié)點(diǎn)、屬性或元素。如果結(jié)果是一個(gè)元素,那么該元素必須有一個(gè)單獨(dú)的文本節(jié)點(diǎn)作為其子節(jié)點(diǎn),函數(shù)返回的就是這個(gè)值。可以使用初始斜杠指定絕對(duì)XPath_string,也可以通過(guò)省略初始斜杠指定相對(duì)XPath_string。如果省略初始斜杠,則相對(duì)路徑的上下文默認(rèn)為根節(jié)點(diǎn)。
如果指定的XPath指向具有多個(gè)子節(jié)點(diǎn)的節(jié)點(diǎn),或者指向的節(jié)點(diǎn)具有非文本節(jié)點(diǎn)子節(jié)點(diǎn),則返回錯(cuò)誤。可選的namespace_string必須解析為VARCHAR2值,該值指定前綴的默認(rèn)映射或命名空間映射,在評(píng)估XPath表達(dá)式時(shí)使用該映射或命名空間。
語(yǔ)法
EXTRACTVALUE(XML Type_instance, XPath_string[, namespace_string])
參數(shù)
參數(shù) | 說(shuō)明 |
XMLType_instance | 指定包含XML文檔的XMLType實(shí)例。 |
XPath_string |
|
namespace_string | 可選項(xiàng), |
返回類型
對(duì)于基于XML模式的文檔,如果能夠推斷出返回值的類型,則會(huì)返回適當(dāng)類型的標(biāo)量值。否則,結(jié)果的類型為VARCHAR2。對(duì)于不基于XML模式的文檔,返回類型始終為VARCHAR2。
示例
SELECT warehouse_name,
EXTRACTVALUE(e.warehouse_spec, '/Warehouse/Docks')
"Docks"
FROM warehouses e
WHERE warehouse_spec IS NOT NULL;
WAREHOUSE_NAME Docks
-------------------- ------------
Southlake, Texas 2
San Francisco 1
New Jersey
Seattle, Washington 3
EXISTSNODE
描述
該函數(shù)用于確定使用指定路徑遍歷XML文檔是否存在任何節(jié)點(diǎn)。它將包含XML文檔的XMLType實(shí)例和指定路徑的VARCHAR2
類型XPath字符串作為參數(shù)。可選的namespace_string必須解析為VARCHAR2值,該值指定前綴的默認(rèn)映射或命名空間映射,Oracle數(shù)據(jù)庫(kù)在評(píng)估XPath表達(dá)式時(shí)使用該映射或命名空間。
當(dāng)遍歷XPath之后,如果無(wú)節(jié)點(diǎn)則返回。
如果有節(jié)點(diǎn)存在則返回0。
語(yǔ)法
EXISTSNODE(XMLType_instance, XPath_string[, namespace_string])
參數(shù)
參數(shù) | 說(shuō)明 |
XMLType_instance | 指定包含XML文檔的XMLType實(shí)例。 |
XPath_string |
|
namespace_string | 可選項(xiàng), |
返回類型
返回BOOLEAN
類型數(shù)據(jù)。
示例
SELECT warehouse_id, warehouse_name
FROM warehouses
WHERE EXISTSNODE(warehouse_spec, '/Warehouse/Docks') = 1
ORDER BY warehouse_id;
warehouse_id | warehouse_name
--------------+---------------------
1 | Southlake, Texas
2 | San Francisco
4 | Seattle, Washington
DELETEXML
描述
該函數(shù)用于刪除XML文檔中滿足XPath表達(dá)式的XML節(jié)點(diǎn)。它將XMLType類型的XML文檔和指定路徑的VARCHAR2類型的XPath字符串作為參數(shù)。
遍歷XML文檔之后,如果存在滿足XPath表達(dá)式的XML節(jié)點(diǎn),則將刪除該節(jié)點(diǎn)后的XML文檔返回;如果不存在這樣的節(jié)點(diǎn),則返回原XML文檔。
語(yǔ)法
DELETEXML(XMLType_instance, XPath_string)
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
XMLType_instance | XMLType類型的XML文檔。 |
XPath_string | VARCHAR2類型,指定路徑。 |
返回類型
返回XMLType類型數(shù)據(jù)。
示例
CREATE TABLE SECTION AS
SELECT XMLTYPE('<section>
<question questionID="1">
<answer>US</answer>
<answer>XX</answer>
</question>
</section>') section_xml FROM dual;
-- delete all node
UPDATE SECTION s
SET s.section_xml = deleteXML(s.section_xml,
'//question[@questionID=1]/answer[2]');
SELECT s.section_xml FROM SECTION s;
section_xml
---------------------------
<section> +
<question questionID="1">+
<answer>US</answer> +
+
</question> +
</section> +
(1 row)
INSERTCHILDXML
描述
該函數(shù)用于在滿足XPath表達(dá)式的XML節(jié)點(diǎn)的某一個(gè)子節(jié)點(diǎn)之后插入一個(gè)新的XML節(jié)點(diǎn)。它將XMLType類型的XML文檔、指定路徑的VARCHAR2類型的XPath字符串、VARCHAR2類型的子節(jié)點(diǎn)標(biāo)簽以及XMLType類型的待插入XML節(jié)點(diǎn)作為參數(shù)。
遍歷XML文檔之后,如果存在滿足XPath表達(dá)式的XML節(jié)點(diǎn),且該節(jié)點(diǎn)存在一個(gè)子節(jié)點(diǎn)的標(biāo)簽與給定的子節(jié)點(diǎn)標(biāo)簽一致,則在最后一個(gè)滿足子節(jié)點(diǎn)標(biāo)簽的子節(jié)點(diǎn)之后插入給定的XML節(jié)點(diǎn)。
遍歷XML文檔之后,如果存在滿足XPath表達(dá)式的XML節(jié)點(diǎn),但該節(jié)點(diǎn)沒(méi)有一個(gè)子節(jié)點(diǎn)的標(biāo)簽與給定子節(jié)點(diǎn)的標(biāo)簽一致,則在該節(jié)點(diǎn)的最后,插入給定的XML節(jié)點(diǎn)作為子節(jié)點(diǎn)。
語(yǔ)法
INSERTCHILDXML(XMLType_instance, XPath_string, Node_string, XMLType_instance)
參數(shù)說(shuō)明
參數(shù) | 說(shuō)明 |
XMLType_instance | XMLTyp 類型的XML文檔。 |
XPath_string | VARCHAR2類型,指定路徑。 |
Node_string | VARCHAR2類型,子節(jié)點(diǎn)的標(biāo)簽。 |
XMLType_instance | XMLType類型的XML節(jié)點(diǎn)。 |
返回類型
返回XMLType類型數(shù)據(jù)。
示例
CREATE TABLE SECTION AS
SELECT XMLTYPE('<section>
<question questionID="1">
<answer>US</answer>
<answer>XX</answer>
</question>
</section>') section_xml FROM dual;
-- delete all node
UPDATE SECTION s
SET s.section_xml = deleteXML(s.section_xml,
'//question[@questionID=1]/answer[2]');
SELECT s.section_xml FROM SECTION s;
section_xml
---------------------------
<section> +
<question questionID="1">+
<answer>US</answer> +
+
</question> +
</section> +
(1 row)