Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6bbf751

Browse files
committed
Fix namespace handling in xpath function
Previously, the xml value resulting from an xpath query would not havenamespace declarations if the namespace declarations were attached toan ancestor element in the input xml value. That means the output valuewas not correct XML. Fix that by running the result value throughxmlCopyNode(), which produces the correct namespace declarations.Author: Ali Akbar <the.apaan@gmail.com>
1 parent2049a7d commit6bbf751

File tree

4 files changed

+55
-8
lines changed

4 files changed

+55
-8
lines changed

‎src/backend/utils/adt/xml.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ static bool print_xml_decl(StringInfo buf, const xmlChar *version,
141141
pg_encencoding,intstandalone);
142142
staticxmlDocPtrxml_parse(text*data,XmlOptionTypexmloption_arg,
143143
boolpreserve_whitespace,intencoding);
144-
statictext*xml_xmlnodetoxmltype(xmlNodePtrcur);
144+
statictext*xml_xmlnodetoxmltype(xmlNodePtrcur,PgXmlErrorContext*xmlerrcxt);
145145
staticintxml_xpathobjtoxmlarray(xmlXPathObjectPtrxpathobj,
146-
ArrayBuildState**astate);
146+
ArrayBuildState**astate,
147+
PgXmlErrorContext*xmlerrcxt);
147148
#endif/* USE_LIBXML */
148149

149150
staticStringInfoquery_to_xml_internal(constchar*query,char*tablename,
@@ -3595,26 +3596,41 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
35953596
* return value otherwise)
35963597
*/
35973598
statictext*
3598-
xml_xmlnodetoxmltype(xmlNodePtrcur)
3599+
xml_xmlnodetoxmltype(xmlNodePtrcur,PgXmlErrorContext*xmlerrcxt)
35993600
{
36003601
xmltype*result;
36013602

36023603
if (cur->type==XML_ELEMENT_NODE)
36033604
{
36043605
xmlBufferPtrbuf;
3606+
xmlNodePtrcur_copy;
36053607

36063608
buf=xmlBufferCreate();
3609+
3610+
/*
3611+
* The result of xmlNodeDump() won't contain namespace definitions
3612+
* from parent nodes, but xmlCopyNode() duplicates a node along with
3613+
* its required namespace definitions.
3614+
*/
3615+
cur_copy=xmlCopyNode(cur,1);
3616+
3617+
if (cur_copy==NULL)
3618+
xml_ereport(xmlerrcxt,ERROR,ERRCODE_OUT_OF_MEMORY,
3619+
"could not copy node");
3620+
36073621
PG_TRY();
36083622
{
3609-
xmlNodeDump(buf,NULL,cur,0,1);
3623+
xmlNodeDump(buf,NULL,cur_copy,0,1);
36103624
result=xmlBuffer_to_xmltype(buf);
36113625
}
36123626
PG_CATCH();
36133627
{
3628+
xmlFreeNode(cur_copy);
36143629
xmlBufferFree(buf);
36153630
PG_RE_THROW();
36163631
}
36173632
PG_END_TRY();
3633+
xmlFreeNode(cur_copy);
36183634
xmlBufferFree(buf);
36193635
}
36203636
else
@@ -3656,7 +3672,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
36563672
*/
36573673
staticint
36583674
xml_xpathobjtoxmlarray(xmlXPathObjectPtrxpathobj,
3659-
ArrayBuildState**astate)
3675+
ArrayBuildState**astate,
3676+
PgXmlErrorContext*xmlerrcxt)
36603677
{
36613678
intresult=0;
36623679
Datumdatum;
@@ -3678,7 +3695,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
36783695

36793696
for (i=0;i<result;i++)
36803697
{
3681-
datum=PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
3698+
datum=PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i],
3699+
xmlerrcxt));
36823700
*astate=accumArrayResult(*astate,datum,
36833701
false,XMLOID,
36843702
CurrentMemoryContext);
@@ -3882,9 +3900,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
38823900
* Extract the results as requested.
38833901
*/
38843902
if (res_nitems!=NULL)
3885-
*res_nitems=xml_xpathobjtoxmlarray(xpathobj,astate);
3903+
*res_nitems=xml_xpathobjtoxmlarray(xpathobj,astate,xmlerrcxt);
38863904
else
3887-
(void)xml_xpathobjtoxmlarray(xpathobj,astate);
3905+
(void)xml_xpathobjtoxmlarray(xpathobj,astate,xmlerrcxt);
38883906
}
38893907
PG_CATCH();
38903908
{

‎src/test/regress/expected/xml.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,21 @@ SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><loc
584584
{1,2}
585585
(1 row)
586586

587+
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']]);
588+
xpath
589+
------------------------------------------------------------------------------------------------------------------------------------------------
590+
{"<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\"/>"}
591+
(1 row)
592+
593+
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']]);
594+
xpath
595+
--------------------------------------------------------------------------------------
596+
{"<local:piece xmlns:local=\"http://127.0.0.1\" xmlns=\"http://127.0.0.2\" id=\"1\">+
597+
<internal>number one</internal> +
598+
<internal2/> +
599+
</local:piece>","<local:piece xmlns:local=\"http://127.0.0.1\" id=\"2\"/>"}
600+
(1 row)
601+
587602
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
588603
xpath
589604
-------------------------

‎src/test/regress/expected/xml_1.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,18 @@ LINE 1: SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="ht...
498498
^
499499
DETAIL: This functionality requires the server to be built with libxml support.
500500
HINT: You need to rebuild PostgreSQL using --with-libxml.
501+
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']]);
502+
ERROR: unsupported XML feature
503+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
504+
^
505+
DETAIL: This functionality requires the server to be built with libxml support.
506+
HINT: You need to rebuild PostgreSQL using --with-libxml.
507+
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']]);
508+
ERROR: unsupported XML feature
509+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
510+
^
511+
DETAIL: This functionality requires the server to be built with libxml support.
512+
HINT: You need to rebuild PostgreSQL using --with-libxml.
501513
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
502514
ERROR: unsupported XML feature
503515
LINE 1: SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>'...

‎src/test/regress/sql/xml.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ SELECT xpath(NULL, NULL) IS NULL FROM xmltest;
174174
SELECT xpath('','<!-- error -->');
175175
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>');
176176
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']]);
177+
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']]);
178+
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']]);
177179
SELECT xpath('//b','<a>one <b>two</b> three <b>etc</b></a>');
178180
SELECT xpath('//text()','<root>&lt;</root>');
179181
SELECT xpath('//@value','<root value="&lt;"/>');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp