@@ -757,7 +757,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
757
757
758
758
/* This attaches root to doc, so we need not free it separately. */
759
759
xmlDocSetRootElement (doc , root );
760
- xmlAddChild (root , content_nodes );
760
+ xmlAddChildList (root , content_nodes );
761
761
762
762
/*
763
763
* We use this node to insert newlines in the dump. Note: in at
@@ -1696,9 +1696,9 @@ xml_doctype_in_content(const xmlChar *str)
1696
1696
* XmlOptionType actually used to parse the input (typically the same as
1697
1697
* xmloption_arg, but a DOCTYPE node in the input can force DOCUMENT mode).
1698
1698
*
1699
- * If parsed_nodes isn't NULL and the input is not an XML document , the list
1700
- * of parsed nodes from the xmlParseBalancedChunkMemory call will be returned
1701
- * to *parsed_nodes.
1699
+ * If parsed_nodes isn't NULL and we parse in CONTENT mode , the list
1700
+ * of parsed nodes from the xmlParseInNodeContext call will be returned
1701
+ * to *parsed_nodes. (It is caller's responsibility to free that.)
1702
1702
*
1703
1703
* Errors normally result in ereport(ERROR), but if escontext is an
1704
1704
* ErrorSaveContext, then "safe" errors are reported there instead, and the
@@ -1750,6 +1750,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1750
1750
PG_TRY ();
1751
1751
{
1752
1752
bool parse_as_document = false;
1753
+ int options ;
1753
1754
int res_code ;
1754
1755
size_t count = 0 ;
1755
1756
xmlChar * version = NULL ;
@@ -1758,11 +1759,6 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1758
1759
/* Any errors here are reported as hard ereport's */
1759
1760
xmlInitParser ();
1760
1761
1761
- ctxt = xmlNewParserCtxt ();
1762
- if (ctxt == NULL || xmlerrcxt -> err_occurred )
1763
- xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
1764
- "could not allocate parser context" );
1765
-
1766
1762
/* Decide whether to parse as document or content */
1767
1763
if (xmloption_arg == XMLOPTION_DOCUMENT )
1768
1764
parse_as_document = true;
@@ -1785,6 +1781,18 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1785
1781
parse_as_document = true;
1786
1782
}
1787
1783
1784
+ /*
1785
+ * Select parse options.
1786
+ *
1787
+ * Note that here we try to apply DTD defaults (XML_PARSE_DTDATTR)
1788
+ * according to SQL/XML:2008 GR 10.16.7.d: 'Default values defined by
1789
+ * internal DTD are applied'. As for external DTDs, we try to support
1790
+ * them too (see SQL/XML:2008 GR 10.16.7.e), but that doesn't really
1791
+ * happen because xmlPgEntityLoader prevents it.
1792
+ */
1793
+ options = XML_PARSE_NOENT | XML_PARSE_DTDATTR
1794
+ | (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS );
1795
+
1788
1796
/* initialize output parameters */
1789
1797
if (parsed_xmloptiontype != NULL )
1790
1798
* parsed_xmloptiontype = parse_as_document ? XMLOPTION_DOCUMENT :
@@ -1794,18 +1802,16 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1794
1802
1795
1803
if (parse_as_document )
1796
1804
{
1797
- /*
1798
- * Note, that here we try to apply DTD defaults
1799
- * (XML_PARSE_DTDATTR) according to SQL/XML:2008 GR 10.16.7.d:
1800
- * 'Default values defined by internal DTD are applied'. As for
1801
- * external DTDs, we try to support them too, (see SQL/XML:2008 GR
1802
- * 10.16.7.e)
1803
- */
1805
+ ctxt = xmlNewParserCtxt ();
1806
+ if (ctxt == NULL || xmlerrcxt -> err_occurred )
1807
+ xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
1808
+ "could not allocate parser context" );
1809
+
1804
1810
doc = xmlCtxtReadDoc (ctxt , utf8string ,
1805
- NULL ,
1811
+ NULL , /* no URL */
1806
1812
"UTF-8" ,
1807
- XML_PARSE_NOENT | XML_PARSE_DTDATTR
1808
- | ( preserve_whitespace ? 0 : XML_PARSE_NOBLANKS ));
1813
+ options );
1814
+
1809
1815
if (doc == NULL || xmlerrcxt -> err_occurred )
1810
1816
{
1811
1817
/* Use original option to decide which error code to report */
@@ -1822,6 +1828,9 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1822
1828
}
1823
1829
else
1824
1830
{
1831
+ xmlNodePtr root ;
1832
+
1833
+ /* set up document with empty root node to be the context node */
1825
1834
doc = xmlNewDoc (version );
1826
1835
if (doc == NULL || xmlerrcxt -> err_occurred )
1827
1836
xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
@@ -1834,19 +1843,38 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1834
1843
"could not allocate XML document" );
1835
1844
doc -> standalone = standalone ;
1836
1845
1846
+ root = xmlNewNode (NULL , (const xmlChar * ) "content-root" );
1847
+ if (root == NULL || xmlerrcxt -> err_occurred )
1848
+ xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
1849
+ "could not allocate xml node" );
1850
+ /* This attaches root to doc, so we need not free it separately. */
1851
+ xmlDocSetRootElement (doc , root );
1852
+
1837
1853
/* allow empty content */
1838
1854
if (* (utf8string + count ))
1839
1855
{
1840
- res_code = xmlParseBalancedChunkMemory (doc , NULL , NULL , 0 ,
1841
- utf8string + count ,
1842
- parsed_nodes );
1843
- if (res_code != 0 || xmlerrcxt -> err_occurred )
1856
+ xmlNodePtr node_list = NULL ;
1857
+ xmlParserErrors res ;
1858
+
1859
+ res = xmlParseInNodeContext (root ,
1860
+ (char * ) utf8string + count ,
1861
+ strlen ((char * ) utf8string + count ),
1862
+ options ,
1863
+ & node_list );
1864
+
1865
+ if (res != XML_ERR_OK || xmlerrcxt -> err_occurred )
1844
1866
{
1867
+ xmlFreeNodeList (node_list );
1845
1868
xml_errsave (escontext , xmlerrcxt ,
1846
1869
ERRCODE_INVALID_XML_CONTENT ,
1847
1870
"invalid XML content" );
1848
1871
goto fail ;
1849
1872
}
1873
+
1874
+ if (parsed_nodes != NULL )
1875
+ * parsed_nodes = node_list ;
1876
+ else
1877
+ xmlFreeNodeList (node_list );
1850
1878
}
1851
1879
}
1852
1880
@@ -1866,7 +1894,8 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
1866
1894
}
1867
1895
PG_END_TRY ();
1868
1896
1869
- xmlFreeParserCtxt (ctxt );
1897
+ if (ctxt != NULL )
1898
+ xmlFreeParserCtxt (ctxt );
1870
1899
1871
1900
pg_xml_done (xmlerrcxt , false);
1872
1901
@@ -2085,6 +2114,19 @@ xml_errorHandler(void *data, PgXmlErrorPtr error)
2085
2114
switch (domain )
2086
2115
{
2087
2116
case XML_FROM_PARSER :
2117
+
2118
+ /*
2119
+ * XML_ERR_NOT_WELL_BALANCED is typically reported after some
2120
+ * other, more on-point error. Furthermore, libxml2 2.13 reports
2121
+ * it under a completely different set of rules than prior
2122
+ * versions. To avoid cross-version behavioral differences,
2123
+ * suppress it so long as we already logged some error.
2124
+ */
2125
+ if (error -> code == XML_ERR_NOT_WELL_BALANCED &&
2126
+ xmlerrcxt -> err_occurred )
2127
+ return ;
2128
+ /* fall through */
2129
+
2088
2130
case XML_FROM_NONE :
2089
2131
case XML_FROM_MEMORY :
2090
2132
case XML_FROM_IO :
0 commit comments