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

Commit79af9a1

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 parent3fabed0 commit79af9a1

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,
@@ -3599,26 +3600,41 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
35993600
* return value otherwise)
36003601
*/
36013602
statictext*
3602-
xml_xmlnodetoxmltype(xmlNodePtrcur)
3603+
xml_xmlnodetoxmltype(xmlNodePtrcur,PgXmlErrorContext*xmlerrcxt)
36033604
{
36043605
xmltype*result;
36053606

36063607
if (cur->type==XML_ELEMENT_NODE)
36073608
{
36083609
xmlBufferPtrbuf;
3610+
xmlNodePtrcur_copy;
36093611

36103612
buf=xmlBufferCreate();
3613+
3614+
/*
3615+
* The result of xmlNodeDump() won't contain namespace definitions
3616+
* from parent nodes, but xmlCopyNode() duplicates a node along with
3617+
* its required namespace definitions.
3618+
*/
3619+
cur_copy=xmlCopyNode(cur,1);
3620+
3621+
if (cur_copy==NULL)
3622+
xml_ereport(xmlerrcxt,ERROR,ERRCODE_OUT_OF_MEMORY,
3623+
"could not copy node");
3624+
36113625
PG_TRY();
36123626
{
3613-
xmlNodeDump(buf,NULL,cur,0,1);
3627+
xmlNodeDump(buf,NULL,cur_copy,0,1);
36143628
result=xmlBuffer_to_xmltype(buf);
36153629
}
36163630
PG_CATCH();
36173631
{
3632+
xmlFreeNode(cur_copy);
36183633
xmlBufferFree(buf);
36193634
PG_RE_THROW();
36203635
}
36213636
PG_END_TRY();
3637+
xmlFreeNode(cur_copy);
36223638
xmlBufferFree(buf);
36233639
}
36243640
else
@@ -3660,7 +3676,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
36603676
*/
36613677
staticint
36623678
xml_xpathobjtoxmlarray(xmlXPathObjectPtrxpathobj,
3663-
ArrayBuildState*astate)
3679+
ArrayBuildState*astate,
3680+
PgXmlErrorContext*xmlerrcxt)
36643681
{
36653682
intresult=0;
36663683
Datumdatum;
@@ -3679,7 +3696,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
36793696

36803697
for (i=0;i<result;i++)
36813698
{
3682-
datum=PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
3699+
datum=PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i],
3700+
xmlerrcxt));
36833701
(void)accumArrayResult(astate,datum, false,
36843702
XMLOID,CurrentMemoryContext);
36853703
}
@@ -3881,9 +3899,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
38813899
* Extract the results as requested.
38823900
*/
38833901
if (res_nitems!=NULL)
3884-
*res_nitems=xml_xpathobjtoxmlarray(xpathobj,astate);
3902+
*res_nitems=xml_xpathobjtoxmlarray(xpathobj,astate,xmlerrcxt);
38853903
else
3886-
(void)xml_xpathobjtoxmlarray(xpathobj,astate);
3904+
(void)xml_xpathobjtoxmlarray(xpathobj,astate,xmlerrcxt);
38873905
}
38883906
PG_CATCH();
38893907
{

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

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

615+
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']]);
616+
xpath
617+
------------------------------------------------------------------------------------------------------------------------------------------------
618+
{"<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\"/>"}
619+
(1 row)
620+
621+
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']]);
622+
xpath
623+
--------------------------------------------------------------------------------------
624+
{"<local:piece xmlns:local=\"http://127.0.0.1\" xmlns=\"http://127.0.0.2\" id=\"1\">+
625+
<internal>number one</internal> +
626+
<internal2/> +
627+
</local:piece>","<local:piece xmlns:local=\"http://127.0.0.1\" id=\"2\"/>"}
628+
(1 row)
629+
615630
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
616631
xpath
617632
-------------------------

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,18 @@ LINE 1: SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="ht...
514514
^
515515
DETAIL: This functionality requires the server to be built with libxml support.
516516
HINT: You need to rebuild PostgreSQL using --with-libxml.
517+
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']]);
518+
ERROR: unsupported XML feature
519+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
520+
^
521+
DETAIL: This functionality requires the server to be built with libxml support.
522+
HINT: You need to rebuild PostgreSQL using --with-libxml.
523+
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']]);
524+
ERROR: unsupported XML feature
525+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
526+
^
527+
DETAIL: This functionality requires the server to be built with libxml support.
528+
HINT: You need to rebuild PostgreSQL using --with-libxml.
517529
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
518530
ERROR: unsupported XML feature
519531
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
@@ -178,6 +178,8 @@ SELECT xpath(NULL, NULL) IS NULL FROM xmltest;
178178
SELECT xpath('','<!-- error -->');
179179
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>');
180180
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']]);
181+
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']]);
182+
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']]);
181183
SELECT xpath('//b','<a>one <b>two</b> three <b>etc</b></a>');
182184
SELECT xpath('//text()','<root>&lt;</root>');
183185
SELECT xpath('//@value','<root value="&lt;"/>');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp