xml_2.out 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  1. CREATE TABLE xmltest (
  2. id int,
  3. data xml
  4. );
  5. INSERT INTO xmltest VALUES (1, '<value>one</value>');
  6. INSERT INTO xmltest VALUES (2, '<value>two</value>');
  7. INSERT INTO xmltest VALUES (3, '<wrong');
  8. ERROR: invalid XML content
  9. LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
  10. ^
  11. DETAIL: line 1: Couldn't find end of Start Tag wrong line 1
  12. SELECT * FROM xmltest;
  13. id | data
  14. ----+--------------------
  15. 1 | <value>one</value>
  16. 2 | <value>two</value>
  17. (2 rows)
  18. SELECT xmlcomment('test');
  19. xmlcomment
  20. -------------
  21. <!--test-->
  22. (1 row)
  23. SELECT xmlcomment('-test');
  24. xmlcomment
  25. --------------
  26. <!---test-->
  27. (1 row)
  28. SELECT xmlcomment('test-');
  29. ERROR: invalid XML comment
  30. SELECT xmlcomment('--test');
  31. ERROR: invalid XML comment
  32. SELECT xmlcomment('te st');
  33. xmlcomment
  34. --------------
  35. <!--te st-->
  36. (1 row)
  37. SELECT xmlconcat(xmlcomment('hello'),
  38. xmlelement(NAME qux, 'foo'),
  39. xmlcomment('world'));
  40. xmlconcat
  41. ----------------------------------------
  42. <!--hello--><qux>foo</qux><!--world-->
  43. (1 row)
  44. SELECT xmlconcat('hello', 'you');
  45. xmlconcat
  46. -----------
  47. helloyou
  48. (1 row)
  49. SELECT xmlconcat(1, 2);
  50. ERROR: argument of XMLCONCAT must be type xml, not type integer
  51. LINE 1: SELECT xmlconcat(1, 2);
  52. ^
  53. SELECT xmlconcat('bad', '<syntax');
  54. ERROR: invalid XML content
  55. LINE 1: SELECT xmlconcat('bad', '<syntax');
  56. ^
  57. DETAIL: line 1: Couldn't find end of Start Tag syntax line 1
  58. SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
  59. xmlconcat
  60. --------------
  61. <foo/><bar/>
  62. (1 row)
  63. SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
  64. xmlconcat
  65. -----------------------------------
  66. <?xml version="1.1"?><foo/><bar/>
  67. (1 row)
  68. SELECT xmlconcat(NULL);
  69. xmlconcat
  70. -----------
  71. (1 row)
  72. SELECT xmlconcat(NULL, NULL);
  73. xmlconcat
  74. -----------
  75. (1 row)
  76. SELECT xmlelement(name element,
  77. xmlattributes (1 as one, 'deuce' as two),
  78. 'content');
  79. xmlelement
  80. ------------------------------------------------
  81. <element one="1" two="deuce">content</element>
  82. (1 row)
  83. SELECT xmlelement(name element,
  84. xmlattributes ('unnamed and wrong'));
  85. ERROR: unnamed XML attribute value must be a column reference
  86. LINE 2: xmlattributes ('unnamed and wrong'));
  87. ^
  88. SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
  89. xmlelement
  90. -------------------------------------------
  91. <element><nested>stuff</nested></element>
  92. (1 row)
  93. SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
  94. xmlelement
  95. ----------------------------------------------------------------------
  96. <employee><name>sharon</name><age>25</age><pay>1000</pay></employee>
  97. <employee><name>sam</name><age>30</age><pay>2000</pay></employee>
  98. <employee><name>bill</name><age>20</age><pay>1000</pay></employee>
  99. <employee><name>jeff</name><age>23</age><pay>600</pay></employee>
  100. <employee><name>cim</name><age>30</age><pay>400</pay></employee>
  101. <employee><name>linda</name><age>19</age><pay>100</pay></employee>
  102. (6 rows)
  103. SELECT xmlelement(name duplicate, xmlattributes(1 as a, 2 as b, 3 as a));
  104. ERROR: XML attribute name "a" appears more than once
  105. LINE 1: ...ment(name duplicate, xmlattributes(1 as a, 2 as b, 3 as a));
  106. ^
  107. SELECT xmlelement(name num, 37);
  108. xmlelement
  109. ---------------
  110. <num>37</num>
  111. (1 row)
  112. SELECT xmlelement(name foo, text 'bar');
  113. xmlelement
  114. ----------------
  115. <foo>bar</foo>
  116. (1 row)
  117. SELECT xmlelement(name foo, xml 'bar');
  118. xmlelement
  119. ----------------
  120. <foo>bar</foo>
  121. (1 row)
  122. SELECT xmlelement(name foo, text 'b<a/>r');
  123. xmlelement
  124. -------------------------
  125. <foo>b&lt;a/&gt;r</foo>
  126. (1 row)
  127. SELECT xmlelement(name foo, xml 'b<a/>r');
  128. xmlelement
  129. -------------------
  130. <foo>b<a/>r</foo>
  131. (1 row)
  132. SELECT xmlelement(name foo, array[1, 2, 3]);
  133. xmlelement
  134. -------------------------------------------------------------------------
  135. <foo><element>1</element><element>2</element><element>3</element></foo>
  136. (1 row)
  137. SET xmlbinary TO base64;
  138. SELECT xmlelement(name foo, bytea 'bar');
  139. xmlelement
  140. -----------------
  141. <foo>YmFy</foo>
  142. (1 row)
  143. SET xmlbinary TO hex;
  144. SELECT xmlelement(name foo, bytea 'bar');
  145. xmlelement
  146. -------------------
  147. <foo>626172</foo>
  148. (1 row)
  149. SELECT xmlelement(name foo, xmlattributes(true as bar));
  150. xmlelement
  151. -------------------
  152. <foo bar="true"/>
  153. (1 row)
  154. SELECT xmlelement(name foo, xmlattributes('2009-04-09 00:24:37'::timestamp as bar));
  155. xmlelement
  156. ----------------------------------
  157. <foo bar="2009-04-09T00:24:37"/>
  158. (1 row)
  159. SELECT xmlelement(name foo, xmlattributes('infinity'::timestamp as bar));
  160. ERROR: timestamp out of range
  161. DETAIL: XML does not support infinite timestamp values.
  162. SELECT xmlelement(name foo, xmlattributes('<>&"''' as funny, xml 'b<a/>r' as funnier));
  163. xmlelement
  164. ------------------------------------------------------------
  165. <foo funny="&lt;&gt;&amp;&quot;'" funnier="b&lt;a/&gt;r"/>
  166. (1 row)
  167. SELECT xmlparse(content '');
  168. xmlparse
  169. ----------
  170. (1 row)
  171. SELECT xmlparse(content ' ');
  172. xmlparse
  173. ----------
  174. (1 row)
  175. SELECT xmlparse(content 'abc');
  176. xmlparse
  177. ----------
  178. abc
  179. (1 row)
  180. SELECT xmlparse(content '<abc>x</abc>');
  181. xmlparse
  182. --------------
  183. <abc>x</abc>
  184. (1 row)
  185. SELECT xmlparse(content '<invalidentity>&</invalidentity>');
  186. ERROR: invalid XML content
  187. DETAIL: line 1: xmlParseEntityRef: no name
  188. <invalidentity>&</invalidentity>
  189. ^
  190. line 1: chunk is not well balanced
  191. SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
  192. ERROR: invalid XML content
  193. DETAIL: line 1: Entity 'idontexist' not defined
  194. <undefinedentity>&idontexist;</undefinedentity>
  195. ^
  196. line 1: chunk is not well balanced
  197. SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
  198. xmlparse
  199. ---------------------------
  200. <invalidns xmlns='&lt;'/>
  201. (1 row)
  202. SELECT xmlparse(content '<relativens xmlns=''relative''/>');
  203. xmlparse
  204. --------------------------------
  205. <relativens xmlns='relative'/>
  206. (1 row)
  207. SELECT xmlparse(content '<twoerrors>&idontexist;</unbalanced>');
  208. ERROR: invalid XML content
  209. DETAIL: line 1: Entity 'idontexist' not defined
  210. <twoerrors>&idontexist;</unbalanced>
  211. ^
  212. line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
  213. line 1: chunk is not well balanced
  214. SELECT xmlparse(content '<nosuchprefix:tag/>');
  215. xmlparse
  216. ---------------------
  217. <nosuchprefix:tag/>
  218. (1 row)
  219. SELECT xmlparse(document ' ');
  220. ERROR: invalid XML document
  221. DETAIL: line 1: Start tag expected, '<' not found
  222. SELECT xmlparse(document 'abc');
  223. ERROR: invalid XML document
  224. DETAIL: line 1: Start tag expected, '<' not found
  225. abc
  226. ^
  227. SELECT xmlparse(document '<abc>x</abc>');
  228. xmlparse
  229. --------------
  230. <abc>x</abc>
  231. (1 row)
  232. SELECT xmlparse(document '<invalidentity>&</abc>');
  233. ERROR: invalid XML document
  234. DETAIL: line 1: xmlParseEntityRef: no name
  235. <invalidentity>&</abc>
  236. ^
  237. line 1: Opening and ending tag mismatch: invalidentity line 1 and abc
  238. SELECT xmlparse(document '<undefinedentity>&idontexist;</abc>');
  239. ERROR: invalid XML document
  240. DETAIL: line 1: Entity 'idontexist' not defined
  241. <undefinedentity>&idontexist;</abc>
  242. ^
  243. line 1: Opening and ending tag mismatch: undefinedentity line 1 and abc
  244. SELECT xmlparse(document '<invalidns xmlns=''&lt;''/>');
  245. xmlparse
  246. ---------------------------
  247. <invalidns xmlns='&lt;'/>
  248. (1 row)
  249. SELECT xmlparse(document '<relativens xmlns=''relative''/>');
  250. xmlparse
  251. --------------------------------
  252. <relativens xmlns='relative'/>
  253. (1 row)
  254. SELECT xmlparse(document '<twoerrors>&idontexist;</unbalanced>');
  255. ERROR: invalid XML document
  256. DETAIL: line 1: Entity 'idontexist' not defined
  257. <twoerrors>&idontexist;</unbalanced>
  258. ^
  259. line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
  260. SELECT xmlparse(document '<nosuchprefix:tag/>');
  261. xmlparse
  262. ---------------------
  263. <nosuchprefix:tag/>
  264. (1 row)
  265. SELECT xmlpi(name foo);
  266. xmlpi
  267. ---------
  268. <?foo?>
  269. (1 row)
  270. SELECT xmlpi(name xml);
  271. ERROR: invalid XML processing instruction
  272. DETAIL: XML processing instruction target name cannot be "xml".
  273. SELECT xmlpi(name xmlstuff);
  274. xmlpi
  275. --------------
  276. <?xmlstuff?>
  277. (1 row)
  278. SELECT xmlpi(name foo, 'bar');
  279. xmlpi
  280. -------------
  281. <?foo bar?>
  282. (1 row)
  283. SELECT xmlpi(name foo, 'in?>valid');
  284. ERROR: invalid XML processing instruction
  285. DETAIL: XML processing instruction cannot contain "?>".
  286. SELECT xmlpi(name foo, null);
  287. xmlpi
  288. -------
  289. (1 row)
  290. SELECT xmlpi(name xml, null);
  291. ERROR: invalid XML processing instruction
  292. DETAIL: XML processing instruction target name cannot be "xml".
  293. SELECT xmlpi(name xmlstuff, null);
  294. xmlpi
  295. -------
  296. (1 row)
  297. SELECT xmlpi(name "xml-stylesheet", 'href="mystyle.css" type="text/css"');
  298. xmlpi
  299. -------------------------------------------------------
  300. <?xml-stylesheet href="mystyle.css" type="text/css"?>
  301. (1 row)
  302. SELECT xmlpi(name foo, ' bar');
  303. xmlpi
  304. -------------
  305. <?foo bar?>
  306. (1 row)
  307. SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
  308. xmlroot
  309. ---------
  310. <foo/>
  311. (1 row)
  312. SELECT xmlroot(xml '<foo/>', version '2.0');
  313. xmlroot
  314. -----------------------------
  315. <?xml version="2.0"?><foo/>
  316. (1 row)
  317. SELECT xmlroot(xml '<foo/>', version no value, standalone yes);
  318. xmlroot
  319. ----------------------------------------------
  320. <?xml version="1.0" standalone="yes"?><foo/>
  321. (1 row)
  322. SELECT xmlroot(xml '<?xml version="1.1"?><foo/>', version no value, standalone yes);
  323. xmlroot
  324. ----------------------------------------------
  325. <?xml version="1.0" standalone="yes"?><foo/>
  326. (1 row)
  327. SELECT xmlroot(xmlroot(xml '<foo/>', version '1.0'), version '1.1', standalone no);
  328. xmlroot
  329. ---------------------------------------------
  330. <?xml version="1.1" standalone="no"?><foo/>
  331. (1 row)
  332. SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no);
  333. xmlroot
  334. ---------------------------------------------
  335. <?xml version="1.0" standalone="no"?><foo/>
  336. (1 row)
  337. SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no value);
  338. xmlroot
  339. ---------
  340. <foo/>
  341. (1 row)
  342. SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value);
  343. xmlroot
  344. ----------------------------------------------
  345. <?xml version="1.0" standalone="yes"?><foo/>
  346. (1 row)
  347. SELECT xmlroot (
  348. xmlelement (
  349. name gazonk,
  350. xmlattributes (
  351. 'val' AS name,
  352. 1 + 1 AS num
  353. ),
  354. xmlelement (
  355. NAME qux,
  356. 'foo'
  357. )
  358. ),
  359. version '1.0',
  360. standalone yes
  361. );
  362. xmlroot
  363. ------------------------------------------------------------------------------------------
  364. <?xml version="1.0" standalone="yes"?><gazonk name="val" num="2"><qux>foo</qux></gazonk>
  365. (1 row)
  366. SELECT xmlserialize(content data as character varying(20)) FROM xmltest;
  367. xmlserialize
  368. --------------------
  369. <value>one</value>
  370. <value>two</value>
  371. (2 rows)
  372. SELECT xmlserialize(content 'good' as char(10));
  373. xmlserialize
  374. --------------
  375. good
  376. (1 row)
  377. SELECT xmlserialize(document 'bad' as text);
  378. ERROR: not an XML document
  379. SELECT xml '<foo>bar</foo>' IS DOCUMENT;
  380. ?column?
  381. ----------
  382. t
  383. (1 row)
  384. SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
  385. ?column?
  386. ----------
  387. f
  388. (1 row)
  389. SELECT xml '<abc/>' IS NOT DOCUMENT;
  390. ?column?
  391. ----------
  392. f
  393. (1 row)
  394. SELECT xml 'abc' IS NOT DOCUMENT;
  395. ?column?
  396. ----------
  397. t
  398. (1 row)
  399. SELECT '<>' IS NOT DOCUMENT;
  400. ERROR: invalid XML content
  401. LINE 1: SELECT '<>' IS NOT DOCUMENT;
  402. ^
  403. DETAIL: line 1: StartTag: invalid element name
  404. <>
  405. ^
  406. SELECT xmlagg(data) FROM xmltest;
  407. xmlagg
  408. --------------------------------------
  409. <value>one</value><value>two</value>
  410. (1 row)
  411. SELECT xmlagg(data) FROM xmltest WHERE id > 10;
  412. xmlagg
  413. --------
  414. (1 row)
  415. SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
  416. xmlelement
  417. --------------------------------------------------------------------------------------------------------------------------------
  418. <employees><name>sharon</name><name>sam</name><name>bill</name><name>jeff</name><name>cim</name><name>linda</name></employees>
  419. (1 row)
  420. -- Check mapping SQL identifier to XML name
  421. SELECT xmlpi(name ":::_xml_abc135.%-&_");
  422. xmlpi
  423. -------------------------------------------------
  424. <?_x003A_::_x005F_xml_abc135._x0025_-_x0026__?>
  425. (1 row)
  426. SELECT xmlpi(name "123");
  427. xmlpi
  428. ---------------
  429. <?_x0031_23?>
  430. (1 row)
  431. PREPARE foo (xml) AS SELECT xmlconcat('<foo/>', $1);
  432. SET XML OPTION DOCUMENT;
  433. EXECUTE foo ('<bar/>');
  434. xmlconcat
  435. --------------
  436. <foo/><bar/>
  437. (1 row)
  438. EXECUTE foo ('bad');
  439. ERROR: invalid XML document
  440. LINE 1: EXECUTE foo ('bad');
  441. ^
  442. DETAIL: line 1: Start tag expected, '<' not found
  443. bad
  444. ^
  445. SELECT xml '<!DOCTYPE a><a/><b/>';
  446. ERROR: invalid XML document
  447. LINE 1: SELECT xml '<!DOCTYPE a><a/><b/>';
  448. ^
  449. DETAIL: line 1: Extra content at the end of the document
  450. <!DOCTYPE a><a/><b/>
  451. ^
  452. SET XML OPTION CONTENT;
  453. EXECUTE foo ('<bar/>');
  454. xmlconcat
  455. --------------
  456. <foo/><bar/>
  457. (1 row)
  458. EXECUTE foo ('good');
  459. xmlconcat
  460. ------------
  461. <foo/>good
  462. (1 row)
  463. SELECT xml '<!-- in SQL:2006+ a doc is content too--> <?y z?> <!DOCTYPE a><a/>';
  464. xml
  465. --------------------------------------------------------------------
  466. <!-- in SQL:2006+ a doc is content too--> <?y z?> <!DOCTYPE a><a/>
  467. (1 row)
  468. SELECT xml '<?xml version="1.0"?> <!-- hi--> <!DOCTYPE a><a/>';
  469. xml
  470. ------------------------------
  471. <!-- hi--> <!DOCTYPE a><a/>
  472. (1 row)
  473. SELECT xml '<!DOCTYPE a><a/>';
  474. xml
  475. ------------------
  476. <!DOCTYPE a><a/>
  477. (1 row)
  478. SELECT xml '<!-- hi--> oops <!DOCTYPE a><a/>';
  479. ERROR: invalid XML content
  480. LINE 1: SELECT xml '<!-- hi--> oops <!DOCTYPE a><a/>';
  481. ^
  482. DETAIL: line 1: StartTag: invalid element name
  483. <!-- hi--> oops <!DOCTYPE a><a/>
  484. ^
  485. SELECT xml '<!-- hi--> <oops/> <!DOCTYPE a><a/>';
  486. ERROR: invalid XML content
  487. LINE 1: SELECT xml '<!-- hi--> <oops/> <!DOCTYPE a><a/>';
  488. ^
  489. DETAIL: line 1: StartTag: invalid element name
  490. <!-- hi--> <oops/> <!DOCTYPE a><a/>
  491. ^
  492. SELECT xml '<!DOCTYPE a><a/><b/>';
  493. ERROR: invalid XML content
  494. LINE 1: SELECT xml '<!DOCTYPE a><a/><b/>';
  495. ^
  496. DETAIL: line 1: Extra content at the end of the document
  497. <!DOCTYPE a><a/><b/>
  498. ^
  499. -- Test backwards parsing
  500. CREATE VIEW xmlview1 AS SELECT xmlcomment('test');
  501. CREATE VIEW xmlview2 AS SELECT xmlconcat('hello', 'you');
  502. CREATE VIEW xmlview3 AS SELECT xmlelement(name element, xmlattributes (1 as ":one:", 'deuce' as two), 'content&');
  503. CREATE VIEW xmlview4 AS SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
  504. CREATE VIEW xmlview5 AS SELECT xmlparse(content '<abc>x</abc>');
  505. CREATE VIEW xmlview6 AS SELECT xmlpi(name foo, 'bar');
  506. CREATE VIEW xmlview7 AS SELECT xmlroot(xml '<foo/>', version no value, standalone yes);
  507. CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10));
  508. CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text);
  509. SELECT table_name, view_definition FROM information_schema.views
  510. WHERE table_name LIKE 'xmlview%' ORDER BY 1;
  511. table_name | view_definition
  512. ------------+-------------------------------------------------------------------------------------------------------------------
  513. xmlview1 | SELECT xmlcomment('test'::text) AS xmlcomment;
  514. xmlview2 | SELECT XMLCONCAT('hello'::xml, 'you'::xml) AS "xmlconcat";
  515. xmlview3 | SELECT XMLELEMENT(NAME element, XMLATTRIBUTES(1 AS ":one:", 'deuce' AS two), 'content&') AS "xmlelement";
  516. xmlview4 | SELECT XMLELEMENT(NAME employee, XMLFOREST(emp.name AS name, emp.age AS age, emp.salary AS pay)) AS "xmlelement"+
  517. | FROM emp;
  518. xmlview5 | SELECT XMLPARSE(CONTENT '<abc>x</abc>'::text STRIP WHITESPACE) AS "xmlparse";
  519. xmlview6 | SELECT XMLPI(NAME foo, 'bar'::text) AS "xmlpi";
  520. xmlview7 | SELECT XMLROOT('<foo/>'::xml, VERSION NO VALUE, STANDALONE YES) AS "xmlroot";
  521. xmlview8 | SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10)))::character(10) AS "xmlserialize";
  522. xmlview9 | SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text) AS "xmlserialize";
  523. (9 rows)
  524. -- Text XPath expressions evaluation
  525. SELECT xpath('/value', data) FROM xmltest;
  526. xpath
  527. ----------------------
  528. {<value>one</value>}
  529. {<value>two</value>}
  530. (2 rows)
  531. SELECT xpath(NULL, NULL) IS NULL FROM xmltest;
  532. ?column?
  533. ----------
  534. t
  535. t
  536. (2 rows)
  537. SELECT xpath('', '<!-- error -->');
  538. ERROR: empty XPath expression
  539. CONTEXT: SQL function "xpath" statement 1
  540. SELECT xpath('//text()', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
  541. xpath
  542. ----------------
  543. {"number one"}
  544. (1 row)
  545. SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
  546. xpath
  547. -------
  548. {1,2}
  549. (1 row)
  550. SELECT xpath('//loc:piece', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
  551. xpath
  552. ------------------------------------------------------------------------------------------------------------------------------------------------
  553. {"<local:piece xmlns:local=\"http://127.0.0.1\" id=\"1\">number one</local:piece>","<local:piece xmlns:local=\"http://127.0.0.1\" id=\"2\"/>"}
  554. (1 row)
  555. SELECT xpath('//loc:piece', '<local:data xmlns:local="http://127.0.0.1" xmlns="http://127.0.0.2"><local:piece id="1"><internal>number one</internal><internal2/></local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
  556. xpath
  557. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  558. {"<local:piece xmlns:local=\"http://127.0.0.1\" xmlns=\"http://127.0.0.2\" id=\"1\"><internal>number one</internal><internal2/></local:piece>","<local:piece xmlns:local=\"http://127.0.0.1\" id=\"2\"/>"}
  559. (1 row)
  560. SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
  561. xpath
  562. -------------------------
  563. {<b>two</b>,<b>etc</b>}
  564. (1 row)
  565. SELECT xpath('//text()', '<root>&lt;</root>');
  566. xpath
  567. --------
  568. {&lt;}
  569. (1 row)
  570. SELECT xpath('//@value', '<root value="&lt;"/>');
  571. xpath
  572. --------
  573. {&lt;}
  574. (1 row)
  575. SELECT xpath('''<<invalid>>''', '<root/>');
  576. xpath
  577. ---------------------------
  578. {&lt;&lt;invalid&gt;&gt;}
  579. (1 row)
  580. SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
  581. xpath
  582. -------
  583. {3}
  584. (1 row)
  585. SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
  586. xpath
  587. ---------
  588. {false}
  589. (1 row)
  590. SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
  591. xpath
  592. --------
  593. {true}
  594. (1 row)
  595. SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
  596. xpath
  597. --------
  598. {root}
  599. (1 row)
  600. SELECT xpath('/nosuchtag', '<root/>');
  601. xpath
  602. -------
  603. {}
  604. (1 row)
  605. SELECT xpath('root', '<root/>');
  606. xpath
  607. -----------
  608. {<root/>}
  609. (1 row)
  610. -- Round-trip non-ASCII data through xpath().
  611. DO $$
  612. DECLARE
  613. xml_declaration text := '<?xml version="1.0" encoding="ISO-8859-1"?>';
  614. degree_symbol text;
  615. res xml[];
  616. BEGIN
  617. -- Per the documentation, except when the server encoding is UTF8, xpath()
  618. -- may not work on non-ASCII data. The untranslatable_character and
  619. -- undefined_function traps below, currently dead code, will become relevant
  620. -- if we remove this limitation.
  621. IF current_setting('server_encoding') <> 'UTF8' THEN
  622. RAISE LOG 'skip: encoding % unsupported for xpath',
  623. current_setting('server_encoding');
  624. RETURN;
  625. END IF;
  626. degree_symbol := convert_from('\xc2b0', 'UTF8');
  627. res := xpath('text()', (xml_declaration ||
  628. '<x>' || degree_symbol || '</x>')::xml);
  629. IF degree_symbol <> res[1]::text THEN
  630. RAISE 'expected % (%), got % (%)',
  631. degree_symbol, convert_to(degree_symbol, 'UTF8'),
  632. res[1], convert_to(res[1]::text, 'UTF8');
  633. END IF;
  634. EXCEPTION
  635. -- character with byte sequence 0xc2 0xb0 in encoding "UTF8" has no equivalent in encoding "LATIN8"
  636. WHEN untranslatable_character
  637. -- default conversion function for encoding "UTF8" to "MULE_INTERNAL" does not exist
  638. OR undefined_function
  639. -- unsupported XML feature
  640. OR feature_not_supported THEN
  641. RAISE LOG 'skip: %', SQLERRM;
  642. END
  643. $$;
  644. -- Test xmlexists and xpath_exists
  645. SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
  646. xmlexists
  647. -----------
  648. f
  649. (1 row)
  650. SELECT xmlexists('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
  651. xmlexists
  652. -----------
  653. t
  654. (1 row)
  655. SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
  656. xmlexists
  657. -----------
  658. t
  659. (1 row)
  660. SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
  661. xpath_exists
  662. --------------
  663. f
  664. (1 row)
  665. SELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
  666. xpath_exists
  667. --------------
  668. t
  669. (1 row)
  670. SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
  671. xpath_exists
  672. --------------
  673. t
  674. (1 row)
  675. INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  676. INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  677. INSERT INTO xmltest VALUES (6, '<myns:menu xmlns:myns="http://myns.com"><myns:beers><myns:name>Budvar</myns:name><myns:cost>free</myns:cost><myns:name>Carling</myns:name><myns:cost>lots</myns:cost></myns:beers></myns:menu>'::xml);
  678. INSERT INTO xmltest VALUES (7, '<myns:menu xmlns:myns="http://myns.com"><myns:beers><myns:name>Molson</myns:name><myns:cost>free</myns:cost><myns:name>Carling</myns:name><myns:cost>lots</myns:cost></myns:beers></myns:menu>'::xml);
  679. SELECT COUNT(id) FROM xmltest WHERE xmlexists('/menu/beer' PASSING data);
  680. count
  681. -------
  682. 0
  683. (1 row)
  684. SELECT COUNT(id) FROM xmltest WHERE xmlexists('/menu/beer' PASSING BY REF data BY REF);
  685. count
  686. -------
  687. 0
  688. (1 row)
  689. SELECT COUNT(id) FROM xmltest WHERE xmlexists('/menu/beers' PASSING BY REF data);
  690. count
  691. -------
  692. 2
  693. (1 row)
  694. SELECT COUNT(id) FROM xmltest WHERE xmlexists('/menu/beers/name[text() = ''Molson'']' PASSING BY REF data);
  695. count
  696. -------
  697. 1
  698. (1 row)
  699. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/menu/beer',data);
  700. count
  701. -------
  702. 0
  703. (1 row)
  704. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/menu/beers',data);
  705. count
  706. -------
  707. 2
  708. (1 row)
  709. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/menu/beers/name[text() = ''Molson'']',data);
  710. count
  711. -------
  712. 1
  713. (1 row)
  714. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/myns:menu/myns:beer',data,ARRAY[ARRAY['myns','http://myns.com']]);
  715. count
  716. -------
  717. 0
  718. (1 row)
  719. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/myns:menu/myns:beers',data,ARRAY[ARRAY['myns','http://myns.com']]);
  720. count
  721. -------
  722. 2
  723. (1 row)
  724. SELECT COUNT(id) FROM xmltest WHERE xpath_exists('/myns:menu/myns:beers/myns:name[text() = ''Molson'']',data,ARRAY[ARRAY['myns','http://myns.com']]);
  725. count
  726. -------
  727. 1
  728. (1 row)
  729. CREATE TABLE query ( expr TEXT );
  730. INSERT INTO query VALUES ('/menu/beers/cost[text() = ''lots'']');
  731. SELECT COUNT(id) FROM xmltest, query WHERE xmlexists(expr PASSING BY REF data);
  732. count
  733. -------
  734. 2
  735. (1 row)
  736. -- Test xml_is_well_formed and variants
  737. SELECT xml_is_well_formed_document('<foo>bar</foo>');
  738. xml_is_well_formed_document
  739. -----------------------------
  740. t
  741. (1 row)
  742. SELECT xml_is_well_formed_document('abc');
  743. xml_is_well_formed_document
  744. -----------------------------
  745. f
  746. (1 row)
  747. SELECT xml_is_well_formed_content('<foo>bar</foo>');
  748. xml_is_well_formed_content
  749. ----------------------------
  750. t
  751. (1 row)
  752. SELECT xml_is_well_formed_content('abc');
  753. xml_is_well_formed_content
  754. ----------------------------
  755. t
  756. (1 row)
  757. SET xmloption TO DOCUMENT;
  758. SELECT xml_is_well_formed('abc');
  759. xml_is_well_formed
  760. --------------------
  761. f
  762. (1 row)
  763. SELECT xml_is_well_formed('<>');
  764. xml_is_well_formed
  765. --------------------
  766. f
  767. (1 row)
  768. SELECT xml_is_well_formed('<abc/>');
  769. xml_is_well_formed
  770. --------------------
  771. t
  772. (1 row)
  773. SELECT xml_is_well_formed('<foo>bar</foo>');
  774. xml_is_well_formed
  775. --------------------
  776. t
  777. (1 row)
  778. SELECT xml_is_well_formed('<foo>bar</foo');
  779. xml_is_well_formed
  780. --------------------
  781. f
  782. (1 row)
  783. SELECT xml_is_well_formed('<foo><bar>baz</foo>');
  784. xml_is_well_formed
  785. --------------------
  786. f
  787. (1 row)
  788. SELECT xml_is_well_formed('<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
  789. xml_is_well_formed
  790. --------------------
  791. t
  792. (1 row)
  793. SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>');
  794. xml_is_well_formed
  795. --------------------
  796. f
  797. (1 row)
  798. SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>');
  799. xml_is_well_formed
  800. --------------------
  801. t
  802. (1 row)
  803. SELECT xml_is_well_formed('<invalidentity>&</abc>');
  804. xml_is_well_formed
  805. --------------------
  806. f
  807. (1 row)
  808. SELECT xml_is_well_formed('<undefinedentity>&idontexist;</abc>');
  809. xml_is_well_formed
  810. --------------------
  811. f
  812. (1 row)
  813. SELECT xml_is_well_formed('<invalidns xmlns=''&lt;''/>');
  814. xml_is_well_formed
  815. --------------------
  816. t
  817. (1 row)
  818. SELECT xml_is_well_formed('<relativens xmlns=''relative''/>');
  819. xml_is_well_formed
  820. --------------------
  821. t
  822. (1 row)
  823. SELECT xml_is_well_formed('<twoerrors>&idontexist;</unbalanced>');
  824. xml_is_well_formed
  825. --------------------
  826. f
  827. (1 row)
  828. SET xmloption TO CONTENT;
  829. SELECT xml_is_well_formed('abc');
  830. xml_is_well_formed
  831. --------------------
  832. t
  833. (1 row)
  834. -- Since xpath() deals with namespaces, it's a bit stricter about
  835. -- what's well-formed and what's not. If we don't obey these rules
  836. -- (i.e. ignore namespace-related errors from libxml), xpath()
  837. -- fails in subtle ways. The following would for example produce
  838. -- the xml value
  839. -- <invalidns xmlns='<'/>
  840. -- which is invalid because '<' may not appear un-escaped in
  841. -- attribute values.
  842. -- Since different libxml versions emit slightly different
  843. -- error messages, we suppress the DETAIL in this test.
  844. \set VERBOSITY terse
  845. SELECT xpath('/*', '<invalidns xmlns=''&lt;''/>');
  846. ERROR: could not parse XML document
  847. \set VERBOSITY default
  848. -- Again, the XML isn't well-formed for namespace purposes
  849. SELECT xpath('/*', '<nosuchprefix:tag/>');
  850. ERROR: could not parse XML document
  851. DETAIL: line 1: Namespace prefix nosuchprefix on tag is not defined
  852. <nosuchprefix:tag/>
  853. ^
  854. CONTEXT: SQL function "xpath" statement 1
  855. -- XPath deprecates relative namespaces, but they're not supposed to
  856. -- throw an error, only a warning.
  857. SELECT xpath('/*', '<relativens xmlns=''relative''/>');
  858. WARNING: line 1: xmlns: URI relative is not absolute
  859. <relativens xmlns='relative'/>
  860. ^
  861. xpath
  862. --------------------------------------
  863. {"<relativens xmlns=\"relative\"/>"}
  864. (1 row)
  865. -- External entity references should not leak filesystem information.
  866. SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>');
  867. xmlparse
  868. -----------------------------------------------------------------
  869. <!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>
  870. (1 row)
  871. SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>');
  872. xmlparse
  873. -----------------------------------------------------------------------
  874. <!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>
  875. (1 row)
  876. -- This might or might not load the requested DTD, but it mustn't throw error.
  877. SELECT XMLPARSE(DOCUMENT '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>');
  878. xmlparse
  879. ------------------------------------------------------------------------------------------------------------------------------------------------------
  880. <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>
  881. (1 row)
  882. -- XMLPATH tests
  883. CREATE TABLE xmldata(data xml);
  884. INSERT INTO xmldata VALUES('<ROWS>
  885. <ROW id="1">
  886. <COUNTRY_ID>AU</COUNTRY_ID>
  887. <COUNTRY_NAME>Australia</COUNTRY_NAME>
  888. <REGION_ID>3</REGION_ID>
  889. </ROW>
  890. <ROW id="2">
  891. <COUNTRY_ID>CN</COUNTRY_ID>
  892. <COUNTRY_NAME>China</COUNTRY_NAME>
  893. <REGION_ID>3</REGION_ID>
  894. </ROW>
  895. <ROW id="3">
  896. <COUNTRY_ID>HK</COUNTRY_ID>
  897. <COUNTRY_NAME>HongKong</COUNTRY_NAME>
  898. <REGION_ID>3</REGION_ID>
  899. </ROW>
  900. <ROW id="4">
  901. <COUNTRY_ID>IN</COUNTRY_ID>
  902. <COUNTRY_NAME>India</COUNTRY_NAME>
  903. <REGION_ID>3</REGION_ID>
  904. </ROW>
  905. <ROW id="5">
  906. <COUNTRY_ID>JP</COUNTRY_ID>
  907. <COUNTRY_NAME>Japan</COUNTRY_NAME>
  908. <REGION_ID>3</REGION_ID><PREMIER_NAME>Sinzo Abe</PREMIER_NAME>
  909. </ROW>
  910. <ROW id="6">
  911. <COUNTRY_ID>SG</COUNTRY_ID>
  912. <COUNTRY_NAME>Singapore</COUNTRY_NAME>
  913. <REGION_ID>3</REGION_ID><SIZE unit="km">791</SIZE>
  914. </ROW>
  915. </ROWS>');
  916. -- XMLTABLE with columns
  917. SELECT xmltable.*
  918. FROM (SELECT data FROM xmldata) x,
  919. LATERAL XMLTABLE('/ROWS/ROW'
  920. PASSING data
  921. COLUMNS id int PATH '@id',
  922. _id FOR ORDINALITY,
  923. country_name text PATH 'COUNTRY_NAME/text()' NOT NULL,
  924. country_id text PATH 'COUNTRY_ID',
  925. region_id int PATH 'REGION_ID',
  926. size float PATH 'SIZE',
  927. unit text PATH 'SIZE/@unit',
  928. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  929. id | _id | country_name | country_id | region_id | size | unit | premier_name
  930. ----+-----+--------------+------------+-----------+------+------+---------------
  931. 1 | 1 | Australia | AU | 3 | | | not specified
  932. 2 | 2 | China | CN | 3 | | | not specified
  933. 3 | 3 | HongKong | HK | 3 | | | not specified
  934. 4 | 4 | India | IN | 3 | | | not specified
  935. 5 | 5 | Japan | JP | 3 | | | Sinzo Abe
  936. 6 | 6 | Singapore | SG | 3 | 791 | km | not specified
  937. (6 rows)
  938. CREATE VIEW xmltableview1 AS SELECT xmltable.*
  939. FROM (SELECT data FROM xmldata) x,
  940. LATERAL XMLTABLE('/ROWS/ROW'
  941. PASSING data
  942. COLUMNS id int PATH '@id',
  943. _id FOR ORDINALITY,
  944. country_name text PATH 'COUNTRY_NAME/text()' NOT NULL,
  945. country_id text PATH 'COUNTRY_ID',
  946. region_id int PATH 'REGION_ID',
  947. size float PATH 'SIZE',
  948. unit text PATH 'SIZE/@unit',
  949. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  950. SELECT * FROM xmltableview1;
  951. id | _id | country_name | country_id | region_id | size | unit | premier_name
  952. ----+-----+--------------+------------+-----------+------+------+---------------
  953. 1 | 1 | Australia | AU | 3 | | | not specified
  954. 2 | 2 | China | CN | 3 | | | not specified
  955. 3 | 3 | HongKong | HK | 3 | | | not specified
  956. 4 | 4 | India | IN | 3 | | | not specified
  957. 5 | 5 | Japan | JP | 3 | | | Sinzo Abe
  958. 6 | 6 | Singapore | SG | 3 | 791 | km | not specified
  959. (6 rows)
  960. \sv xmltableview1
  961. CREATE OR REPLACE VIEW public.xmltableview1 AS
  962. SELECT "xmltable".id,
  963. "xmltable"._id,
  964. "xmltable".country_name,
  965. "xmltable".country_id,
  966. "xmltable".region_id,
  967. "xmltable".size,
  968. "xmltable".unit,
  969. "xmltable".premier_name
  970. FROM ( SELECT xmldata.data
  971. FROM xmldata) x,
  972. LATERAL XMLTABLE(('/ROWS/ROW'::text) PASSING (x.data) COLUMNS id integer PATH ('@id'::text), _id FOR ORDINALITY, country_name text PATH ('COUNTRY_NAME/text()'::text) NOT NULL, country_id text PATH ('COUNTRY_ID'::text), region_id integer PATH ('REGION_ID'::text), size double precision PATH ('SIZE'::text), unit text PATH ('SIZE/@unit'::text), premier_name text DEFAULT ('not specified'::text) PATH ('PREMIER_NAME'::text))
  973. EXPLAIN (COSTS OFF) SELECT * FROM xmltableview1;
  974. QUERY PLAN
  975. -----------------------------------------
  976. Nested Loop
  977. -> Seq Scan on xmldata
  978. -> Table Function Scan on "xmltable"
  979. (3 rows)
  980. EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
  981. QUERY PLAN
  982. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  983. Nested Loop
  984. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  985. -> Seq Scan on public.xmldata
  986. Output: xmldata.data
  987. -> Table Function Scan on "xmltable"
  988. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  989. Table Function Call: XMLTABLE(('/ROWS/ROW'::text) PASSING (xmldata.data) COLUMNS id integer PATH ('@id'::text), _id FOR ORDINALITY, country_name text PATH ('COUNTRY_NAME/text()'::text) NOT NULL, country_id text PATH ('COUNTRY_ID'::text), region_id integer PATH ('REGION_ID'::text), size double precision PATH ('SIZE'::text), unit text PATH ('SIZE/@unit'::text), premier_name text DEFAULT ('not specified'::text) PATH ('PREMIER_NAME'::text))
  990. (7 rows)
  991. -- errors
  992. SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
  993. ERROR: XMLTABLE function has 1 columns available but 2 columns specified
  994. -- XMLNAMESPACES tests
  995. SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
  996. '/zz:rows/zz:row'
  997. PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
  998. COLUMNS a int PATH 'zz:a');
  999. a
  1000. ----
  1001. 10
  1002. (1 row)
  1003. CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
  1004. '/zz:rows/zz:row'
  1005. PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
  1006. COLUMNS a int PATH 'zz:a');
  1007. SELECT * FROM xmltableview2;
  1008. a
  1009. ----
  1010. 10
  1011. (1 row)
  1012. SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'),
  1013. '/rows/row'
  1014. PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
  1015. COLUMNS a int PATH 'a');
  1016. ERROR: DEFAULT namespace is not supported
  1017. SELECT * FROM XMLTABLE('.'
  1018. PASSING '<foo/>'
  1019. COLUMNS a text PATH 'foo/namespace::node()');
  1020. a
  1021. --------------------------------------
  1022. http://www.w3.org/XML/1998/namespace
  1023. (1 row)
  1024. -- used in prepare statements
  1025. PREPARE pp AS
  1026. SELECT xmltable.*
  1027. FROM (SELECT data FROM xmldata) x,
  1028. LATERAL XMLTABLE('/ROWS/ROW'
  1029. PASSING data
  1030. COLUMNS id int PATH '@id',
  1031. _id FOR ORDINALITY,
  1032. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1033. country_id text PATH 'COUNTRY_ID',
  1034. region_id int PATH 'REGION_ID',
  1035. size float PATH 'SIZE',
  1036. unit text PATH 'SIZE/@unit',
  1037. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  1038. EXECUTE pp;
  1039. id | _id | country_name | country_id | region_id | size | unit | premier_name
  1040. ----+-----+--------------+------------+-----------+------+------+---------------
  1041. 1 | 1 | Australia | AU | 3 | | | not specified
  1042. 2 | 2 | China | CN | 3 | | | not specified
  1043. 3 | 3 | HongKong | HK | 3 | | | not specified
  1044. 4 | 4 | India | IN | 3 | | | not specified
  1045. 5 | 5 | Japan | JP | 3 | | | Sinzo Abe
  1046. 6 | 6 | Singapore | SG | 3 | 791 | km | not specified
  1047. (6 rows)
  1048. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS "COUNTRY_NAME" text, "REGION_ID" int);
  1049. COUNTRY_NAME | REGION_ID
  1050. --------------+-----------
  1051. India | 3
  1052. Japan | 3
  1053. (2 rows)
  1054. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id FOR ORDINALITY, "COUNTRY_NAME" text, "REGION_ID" int);
  1055. id | COUNTRY_NAME | REGION_ID
  1056. ----+--------------+-----------
  1057. 1 | India | 3
  1058. 2 | Japan | 3
  1059. (2 rows)
  1060. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id int PATH '@id', "COUNTRY_NAME" text, "REGION_ID" int);
  1061. id | COUNTRY_NAME | REGION_ID
  1062. ----+--------------+-----------
  1063. 4 | India | 3
  1064. 5 | Japan | 3
  1065. (2 rows)
  1066. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id int PATH '@id');
  1067. id
  1068. ----
  1069. 4
  1070. 5
  1071. (2 rows)
  1072. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id FOR ORDINALITY);
  1073. id
  1074. ----
  1075. 1
  1076. 2
  1077. (2 rows)
  1078. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id int PATH '@id', "COUNTRY_NAME" text, "REGION_ID" int, rawdata xml PATH '.');
  1079. id | COUNTRY_NAME | REGION_ID | rawdata
  1080. ----+--------------+-----------+------------------------------------------------------------------
  1081. 4 | India | 3 | <ROW id="4"> +
  1082. | | | <COUNTRY_ID>IN</COUNTRY_ID> +
  1083. | | | <COUNTRY_NAME>India</COUNTRY_NAME> +
  1084. | | | <REGION_ID>3</REGION_ID> +
  1085. | | | </ROW>
  1086. 5 | Japan | 3 | <ROW id="5"> +
  1087. | | | <COUNTRY_ID>JP</COUNTRY_ID> +
  1088. | | | <COUNTRY_NAME>Japan</COUNTRY_NAME> +
  1089. | | | <REGION_ID>3</REGION_ID><PREMIER_NAME>Sinzo Abe</PREMIER_NAME>+
  1090. | | | </ROW>
  1091. (2 rows)
  1092. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS id int PATH '@id', "COUNTRY_NAME" text, "REGION_ID" int, rawdata xml PATH './*');
  1093. id | COUNTRY_NAME | REGION_ID | rawdata
  1094. ----+--------------+-----------+-----------------------------------------------------------------------------------------------------------------------------
  1095. 4 | India | 3 | <COUNTRY_ID>IN</COUNTRY_ID><COUNTRY_NAME>India</COUNTRY_NAME><REGION_ID>3</REGION_ID>
  1096. 5 | Japan | 3 | <COUNTRY_ID>JP</COUNTRY_ID><COUNTRY_NAME>Japan</COUNTRY_NAME><REGION_ID>3</REGION_ID><PREMIER_NAME>Sinzo Abe</PREMIER_NAME>
  1097. (2 rows)
  1098. SELECT * FROM xmltable('/root' passing '<root><element>a1a<!-- aaaa -->a2a<?aaaaa?> <!--z--> bbbb<x>xxx</x>cccc</element></root>' COLUMNS element text);
  1099. element
  1100. ----------------------
  1101. a1aa2a bbbbxxxcccc
  1102. (1 row)
  1103. SELECT * FROM xmltable('/root' passing '<root><element>a1a<!-- aaaa -->a2a<?aaaaa?> <!--z--> bbbb<x>xxx</x>cccc</element></root>' COLUMNS element text PATH 'element/text()'); -- should fail
  1104. ERROR: more than one value returned by column XPath expression
  1105. -- CDATA test
  1106. select * from xmltable('d/r' passing '<d><r><c><![CDATA[<hello> &"<>!<a>foo</a>]]></c></r><r><c>2</c></r></d>' columns c text);
  1107. c
  1108. -------------------------
  1109. <hello> &"<>!<a>foo</a>
  1110. 2
  1111. (2 rows)
  1112. -- XML builtin entities
  1113. SELECT * FROM xmltable('/x/a' PASSING '<x><a><ent>&apos;</ent></a><a><ent>&quot;</ent></a><a><ent>&amp;</ent></a><a><ent>&lt;</ent></a><a><ent>&gt;</ent></a></x>' COLUMNS ent text);
  1114. ent
  1115. -----
  1116. '
  1117. "
  1118. &
  1119. <
  1120. >
  1121. (5 rows)
  1122. SELECT * FROM xmltable('/x/a' PASSING '<x><a><ent>&apos;</ent></a><a><ent>&quot;</ent></a><a><ent>&amp;</ent></a><a><ent>&lt;</ent></a><a><ent>&gt;</ent></a></x>' COLUMNS ent xml);
  1123. ent
  1124. ------------------
  1125. <ent>'</ent>
  1126. <ent>"</ent>
  1127. <ent>&amp;</ent>
  1128. <ent>&lt;</ent>
  1129. <ent>&gt;</ent>
  1130. (5 rows)
  1131. EXPLAIN (VERBOSE, COSTS OFF)
  1132. SELECT xmltable.*
  1133. FROM (SELECT data FROM xmldata) x,
  1134. LATERAL XMLTABLE('/ROWS/ROW'
  1135. PASSING data
  1136. COLUMNS id int PATH '@id',
  1137. _id FOR ORDINALITY,
  1138. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1139. country_id text PATH 'COUNTRY_ID',
  1140. region_id int PATH 'REGION_ID',
  1141. size float PATH 'SIZE',
  1142. unit text PATH 'SIZE/@unit',
  1143. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  1144. QUERY PLAN
  1145. -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1146. Nested Loop
  1147. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  1148. -> Seq Scan on public.xmldata
  1149. Output: xmldata.data
  1150. -> Table Function Scan on "xmltable"
  1151. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  1152. Table Function Call: XMLTABLE(('/ROWS/ROW'::text) PASSING (xmldata.data) COLUMNS id integer PATH ('@id'::text), _id FOR ORDINALITY, country_name text PATH ('COUNTRY_NAME'::text) NOT NULL, country_id text PATH ('COUNTRY_ID'::text), region_id integer PATH ('REGION_ID'::text), size double precision PATH ('SIZE'::text), unit text PATH ('SIZE/@unit'::text), premier_name text DEFAULT ('not specified'::text) PATH ('PREMIER_NAME'::text))
  1153. (7 rows)
  1154. -- test qual
  1155. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS "COUNTRY_NAME" text, "REGION_ID" int) WHERE "COUNTRY_NAME" = 'Japan';
  1156. COUNTRY_NAME | REGION_ID
  1157. --------------+-----------
  1158. Japan | 3
  1159. (1 row)
  1160. EXPLAIN (VERBOSE, COSTS OFF)
  1161. SELECT xmltable.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]' PASSING data COLUMNS "COUNTRY_NAME" text, "REGION_ID" int) WHERE "COUNTRY_NAME" = 'Japan';
  1162. QUERY PLAN
  1163. ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1164. Nested Loop
  1165. Output: "xmltable"."COUNTRY_NAME", "xmltable"."REGION_ID"
  1166. -> Seq Scan on public.xmldata
  1167. Output: xmldata.data
  1168. -> Table Function Scan on "xmltable"
  1169. Output: "xmltable"."COUNTRY_NAME", "xmltable"."REGION_ID"
  1170. Table Function Call: XMLTABLE(('/ROWS/ROW[COUNTRY_NAME="Japan" or COUNTRY_NAME="India"]'::text) PASSING (xmldata.data) COLUMNS "COUNTRY_NAME" text, "REGION_ID" integer)
  1171. Filter: ("xmltable"."COUNTRY_NAME" = 'Japan'::text)
  1172. (8 rows)
  1173. -- should to work with more data
  1174. INSERT INTO xmldata VALUES('<ROWS>
  1175. <ROW id="10">
  1176. <COUNTRY_ID>CZ</COUNTRY_ID>
  1177. <COUNTRY_NAME>Czech Republic</COUNTRY_NAME>
  1178. <REGION_ID>2</REGION_ID><PREMIER_NAME>Milos Zeman</PREMIER_NAME>
  1179. </ROW>
  1180. <ROW id="11">
  1181. <COUNTRY_ID>DE</COUNTRY_ID>
  1182. <COUNTRY_NAME>Germany</COUNTRY_NAME>
  1183. <REGION_ID>2</REGION_ID>
  1184. </ROW>
  1185. <ROW id="12">
  1186. <COUNTRY_ID>FR</COUNTRY_ID>
  1187. <COUNTRY_NAME>France</COUNTRY_NAME>
  1188. <REGION_ID>2</REGION_ID>
  1189. </ROW>
  1190. </ROWS>');
  1191. INSERT INTO xmldata VALUES('<ROWS>
  1192. <ROW id="20">
  1193. <COUNTRY_ID>EG</COUNTRY_ID>
  1194. <COUNTRY_NAME>Egypt</COUNTRY_NAME>
  1195. <REGION_ID>1</REGION_ID>
  1196. </ROW>
  1197. <ROW id="21">
  1198. <COUNTRY_ID>SD</COUNTRY_ID>
  1199. <COUNTRY_NAME>Sudan</COUNTRY_NAME>
  1200. <REGION_ID>1</REGION_ID>
  1201. </ROW>
  1202. </ROWS>');
  1203. SELECT xmltable.*
  1204. FROM (SELECT data FROM xmldata) x,
  1205. LATERAL XMLTABLE('/ROWS/ROW'
  1206. PASSING data
  1207. COLUMNS id int PATH '@id',
  1208. _id FOR ORDINALITY,
  1209. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1210. country_id text PATH 'COUNTRY_ID',
  1211. region_id int PATH 'REGION_ID',
  1212. size float PATH 'SIZE',
  1213. unit text PATH 'SIZE/@unit',
  1214. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  1215. id | _id | country_name | country_id | region_id | size | unit | premier_name
  1216. ----+-----+----------------+------------+-----------+------+------+---------------
  1217. 1 | 1 | Australia | AU | 3 | | | not specified
  1218. 2 | 2 | China | CN | 3 | | | not specified
  1219. 3 | 3 | HongKong | HK | 3 | | | not specified
  1220. 4 | 4 | India | IN | 3 | | | not specified
  1221. 5 | 5 | Japan | JP | 3 | | | Sinzo Abe
  1222. 6 | 6 | Singapore | SG | 3 | 791 | km | not specified
  1223. 10 | 1 | Czech Republic | CZ | 2 | | | Milos Zeman
  1224. 11 | 2 | Germany | DE | 2 | | | not specified
  1225. 12 | 3 | France | FR | 2 | | | not specified
  1226. 20 | 1 | Egypt | EG | 1 | | | not specified
  1227. 21 | 2 | Sudan | SD | 1 | | | not specified
  1228. (11 rows)
  1229. SELECT xmltable.*
  1230. FROM (SELECT data FROM xmldata) x,
  1231. LATERAL XMLTABLE('/ROWS/ROW'
  1232. PASSING data
  1233. COLUMNS id int PATH '@id',
  1234. _id FOR ORDINALITY,
  1235. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1236. country_id text PATH 'COUNTRY_ID',
  1237. region_id int PATH 'REGION_ID',
  1238. size float PATH 'SIZE',
  1239. unit text PATH 'SIZE/@unit',
  1240. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified')
  1241. WHERE region_id = 2;
  1242. id | _id | country_name | country_id | region_id | size | unit | premier_name
  1243. ----+-----+----------------+------------+-----------+------+------+---------------
  1244. 10 | 1 | Czech Republic | CZ | 2 | | | Milos Zeman
  1245. 11 | 2 | Germany | DE | 2 | | | not specified
  1246. 12 | 3 | France | FR | 2 | | | not specified
  1247. (3 rows)
  1248. EXPLAIN (VERBOSE, COSTS OFF)
  1249. SELECT xmltable.*
  1250. FROM (SELECT data FROM xmldata) x,
  1251. LATERAL XMLTABLE('/ROWS/ROW'
  1252. PASSING data
  1253. COLUMNS id int PATH '@id',
  1254. _id FOR ORDINALITY,
  1255. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1256. country_id text PATH 'COUNTRY_ID',
  1257. region_id int PATH 'REGION_ID',
  1258. size float PATH 'SIZE',
  1259. unit text PATH 'SIZE/@unit',
  1260. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified')
  1261. WHERE region_id = 2;
  1262. QUERY PLAN
  1263. -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1264. Nested Loop
  1265. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  1266. -> Seq Scan on public.xmldata
  1267. Output: xmldata.data
  1268. -> Table Function Scan on "xmltable"
  1269. Output: "xmltable".id, "xmltable"._id, "xmltable".country_name, "xmltable".country_id, "xmltable".region_id, "xmltable".size, "xmltable".unit, "xmltable".premier_name
  1270. Table Function Call: XMLTABLE(('/ROWS/ROW'::text) PASSING (xmldata.data) COLUMNS id integer PATH ('@id'::text), _id FOR ORDINALITY, country_name text PATH ('COUNTRY_NAME'::text) NOT NULL, country_id text PATH ('COUNTRY_ID'::text), region_id integer PATH ('REGION_ID'::text), size double precision PATH ('SIZE'::text), unit text PATH ('SIZE/@unit'::text), premier_name text DEFAULT ('not specified'::text) PATH ('PREMIER_NAME'::text))
  1271. Filter: ("xmltable".region_id = 2)
  1272. (8 rows)
  1273. -- should fail, NULL value
  1274. SELECT xmltable.*
  1275. FROM (SELECT data FROM xmldata) x,
  1276. LATERAL XMLTABLE('/ROWS/ROW'
  1277. PASSING data
  1278. COLUMNS id int PATH '@id',
  1279. _id FOR ORDINALITY,
  1280. country_name text PATH 'COUNTRY_NAME' NOT NULL,
  1281. country_id text PATH 'COUNTRY_ID',
  1282. region_id int PATH 'REGION_ID',
  1283. size float PATH 'SIZE' NOT NULL,
  1284. unit text PATH 'SIZE/@unit',
  1285. premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
  1286. ERROR: null is not allowed in column "size"
  1287. -- if all is ok, then result is empty
  1288. -- one line xml test
  1289. WITH
  1290. x AS (SELECT proname, proowner, procost::numeric, pronargs,
  1291. array_to_string(proargnames,',') as proargnames,
  1292. case when proargtypes <> '' then array_to_string(proargtypes::oid[],',') end as proargtypes
  1293. FROM pg_proc WHERE proname = 'f_leak'),
  1294. y AS (SELECT xmlelement(name proc,
  1295. xmlforest(proname, proowner,
  1296. procost, pronargs,
  1297. proargnames, proargtypes)) as proc
  1298. FROM x),
  1299. z AS (SELECT xmltable.*
  1300. FROM y,
  1301. LATERAL xmltable('/proc' PASSING proc
  1302. COLUMNS proname name,
  1303. proowner oid,
  1304. procost float,
  1305. pronargs int,
  1306. proargnames text,
  1307. proargtypes text))
  1308. SELECT * FROM z
  1309. EXCEPT SELECT * FROM x;
  1310. proname | proowner | procost | pronargs | proargnames | proargtypes
  1311. ---------+----------+---------+----------+-------------+-------------
  1312. (0 rows)
  1313. -- multi line xml test, result should be empty too
  1314. WITH
  1315. x AS (SELECT proname, proowner, procost::numeric, pronargs,
  1316. array_to_string(proargnames,',') as proargnames,
  1317. case when proargtypes <> '' then array_to_string(proargtypes::oid[],',') end as proargtypes
  1318. FROM pg_proc),
  1319. y AS (SELECT xmlelement(name data,
  1320. xmlagg(xmlelement(name proc,
  1321. xmlforest(proname, proowner, procost,
  1322. pronargs, proargnames, proargtypes)))) as doc
  1323. FROM x),
  1324. z AS (SELECT xmltable.*
  1325. FROM y,
  1326. LATERAL xmltable('/data/proc' PASSING doc
  1327. COLUMNS proname name,
  1328. proowner oid,
  1329. procost float,
  1330. pronargs int,
  1331. proargnames text,
  1332. proargtypes text))
  1333. SELECT * FROM z
  1334. EXCEPT SELECT * FROM x;
  1335. proname | proowner | procost | pronargs | proargnames | proargtypes
  1336. ---------+----------+---------+----------+-------------+-------------
  1337. (0 rows)
  1338. CREATE TABLE xmltest2(x xml, _path text);
  1339. INSERT INTO xmltest2 VALUES('<d><r><ac>1</ac></r></d>', 'A');
  1340. INSERT INTO xmltest2 VALUES('<d><r><bc>2</bc></r></d>', 'B');
  1341. INSERT INTO xmltest2 VALUES('<d><r><cc>3</cc></r></d>', 'C');
  1342. INSERT INTO xmltest2 VALUES('<d><r><dc>2</dc></r></d>', 'D');
  1343. SELECT xmltable.* FROM xmltest2, LATERAL xmltable('/d/r' PASSING x COLUMNS a int PATH '' || lower(_path) || 'c');
  1344. a
  1345. ---
  1346. 1
  1347. 2
  1348. 3
  1349. 2
  1350. (4 rows)
  1351. SELECT xmltable.* FROM xmltest2, LATERAL xmltable(('/d/r/' || lower(_path) || 'c') PASSING x COLUMNS a int PATH '.');
  1352. a
  1353. ---
  1354. 1
  1355. 2
  1356. 3
  1357. 2
  1358. (4 rows)
  1359. SELECT xmltable.* FROM xmltest2, LATERAL xmltable(('/d/r/' || lower(_path) || 'c') PASSING x COLUMNS a int PATH 'x' DEFAULT ascii(_path) - 54);
  1360. a
  1361. ----
  1362. 11
  1363. 12
  1364. 13
  1365. 14
  1366. (4 rows)
  1367. -- XPath result can be boolean or number too
  1368. SELECT * FROM XMLTABLE('*' PASSING '<a>a</a>' COLUMNS a xml PATH '.', b text PATH '.', c text PATH '"hi"', d boolean PATH '. = "a"', e integer PATH 'string-length(.)');
  1369. a | b | c | d | e
  1370. ----------+---+----+---+---
  1371. <a>a</a> | a | hi | t | 1
  1372. (1 row)
  1373. \x
  1374. SELECT * FROM XMLTABLE('*' PASSING '<e>pre<!--c1--><?pi arg?><![CDATA[&ent1]]><n2>&amp;deep</n2>post</e>' COLUMNS x xml PATH 'node()', y xml PATH '/');
  1375. -[ RECORD 1 ]-----------------------------------------------------------
  1376. x | pre<!--c1--><?pi arg?><![CDATA[&ent1]]><n2>&amp;deep</n2>post
  1377. y | <e>pre<!--c1--><?pi arg?><![CDATA[&ent1]]><n2>&amp;deep</n2>post</e>+
  1378. |
  1379. \x
  1380. SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH '"<foo/>"', b xml PATH '"<foo/>"');
  1381. a | b
  1382. --------+--------------
  1383. <foo/> | &lt;foo/&gt;
  1384. (1 row)