Skip to content

Commit cebb3f0

Browse files
committed
Fix namespace handling in xpath function
Previously, the xml value resulting from an xpath query would not have namespace declarations if the namespace declarations were attached to an ancestor element in the input xml value. That means the output value was not correct XML. Fix that by running the result value through xmlCopyNode(), which produces the correct namespace declarations. Author: Ali Akbar <the.apaan@gmail.com>
1 parent 082764a commit cebb3f0

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

src/backend/utils/adt/xml.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3286,19 +3286,34 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
32863286
if (cur->type == XML_ELEMENT_NODE)
32873287
{
32883288
xmlBufferPtr buf;
3289+
xmlNodePtr cur_copy;
32893290

32903291
buf = xmlBufferCreate();
3292+
3293+
/*
3294+
* The result of xmlNodeDump() won't contain namespace definitions
3295+
* from parent nodes, but xmlCopyNode() duplicates a node along with
3296+
* its required namespace definitions.
3297+
*/
3298+
cur_copy = xmlCopyNode(cur, 1);
3299+
3300+
if (cur_copy == NULL)
3301+
xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY,
3302+
"could not copy node");
3303+
32913304
PG_TRY();
32923305
{
3293-
xmlNodeDump(buf, NULL, cur, 0, 1);
3306+
xmlNodeDump(buf, NULL, cur_copy, 0, 1);
32943307
result = xmlBuffer_to_xmltype(buf);
32953308
}
32963309
PG_CATCH();
32973310
{
3311+
xmlFreeNode(cur_copy);
32983312
xmlBufferFree(buf);
32993313
PG_RE_THROW();
33003314
}
33013315
PG_END_TRY();
3316+
xmlFreeNode(cur_copy);
33023317
xmlBufferFree(buf);
33033318
}
33043319
else

src/test/regress/expected/xml.out

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

499+
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']]);
500+
xpath
501+
------------------------------------------------------------------------------------------------------------------------------------------------
502+
{"<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\"/>"}
503+
(1 row)
504+
505+
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']]);
506+
xpath
507+
--------------------------------------------------------------------------------------
508+
{"<local:piece xmlns:local=\"http://127.0.0.1\" xmlns=\"http://127.0.0.2\" id=\"1\">+
509+
<internal>number one</internal> +
510+
<internal2/> +
511+
</local:piece>","<local:piece xmlns:local=\"http://127.0.0.1\" id=\"2\"/>"}
512+
(1 row)
513+
499514
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
500515
xpath
501516
-------------------------

src/test/regress/expected/xml_1.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,18 @@ LINE 1: SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="ht...
450450
^
451451
DETAIL: This functionality requires the server to be built with libxml support.
452452
HINT: You need to rebuild PostgreSQL using --with-libxml.
453+
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']]);
454+
ERROR: unsupported XML feature
455+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
456+
^
457+
DETAIL: This functionality requires the server to be built with libxml support.
458+
HINT: You need to rebuild PostgreSQL using --with-libxml.
459+
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']]);
460+
ERROR: unsupported XML feature
461+
LINE 1: SELECT xpath('//loc:piece', '<local:data xmlns:local="http:/...
462+
^
463+
DETAIL: This functionality requires the server to be built with libxml support.
464+
HINT: You need to rebuild PostgreSQL using --with-libxml.
453465
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
454466
ERROR: unsupported XML feature
455467
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
@@ -162,6 +162,8 @@ SELECT xpath(NULL, NULL) IS NULL FROM xmltest;
162162
SELECT xpath('', '<!-- error -->');
163163
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>');
164164
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']]);
165+
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']]);
166+
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']]);
165167
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
166168

167169
-- External entity references should not leak filesystem information.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy