+ * CONTENT as originally planned, with libxml reporting any errors.
+ * been called. The input is already in UTF8 encoding.
+ /* if we see
+ if (xmlStrncmp(p, (xmlChar *) "DOCTYPE", 7) == 0)
+ return true;
+
+ /* otherwise, if it's not a comment, fail */
+ if (xmlStrncmp(p, (xmlChar *) "--", 2) != 0)
+ return false;
+ /* find end of comment: find -- and a > must follow */
+ p = xmlStrstr(p + 2, (xmlChar *) "--");
+ if (!p || p[2] != '>')
+ return false;
+ /* advance over comment, and keep scanning */
+ p += 3;
+ continue;
+ }
+
+ /* otherwise, if it's not a PI , fail */
+ if (*p != '?')
+ return false;
+ p++;
+
+ /* find end of PI (the string ?> is forbidden within a PI) */
+ e = xmlStrstr(p, (xmlChar *) "?>");
+ if (!e)
+ return false;
+
+ /* we don't check PIs carefully, but do reject "xml" target */
+ if (e - p >= 3 && xmlStrncasecmp(p, (xmlChar *) "xml", 3) == 0)
+ return false;
+
+ /* advance over PI, keep scanning */
+ p = e + 2;
+ }
+}
+
/*
* Convert a C string to XML internal representation
/* Use a TRY block to ensure we clean up correctly */
PG_TRY();
{
+ bool parse_as_document = false;
+ int res_code;
+ size_t count = 0;
+ xmlChar *version = NULL;
+ int standalone = 0;
+
xmlInitParser();
ctxt = xmlNewParserCtxt();
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
"could not allocate parser context");
+ /* Decide whether to parse as document or content */
if (xmloption_arg == XMLOPTION_DOCUMENT)
+ parse_as_document = true;
+ else
+ {
+ /* Parse and skip over the XML declaration, if any */
+ res_code = parse_xml_decl(utf8string,
+ &count, &version, NULL, &standalone);
+ if (res_code != 0)
+ xml_ereport_by_code(ERROR, ERRCODE_INVALID_XML_CONTENT,
+ "invalid XML content: invalid XML declaration",
+ res_code);
+
+ /* Is there a DOCTYPE element? */
+ if (xml_doctype_in_content(utf8string + count))
+ parse_as_document = true;
+ }
+
+ if (parse_as_document)
{
/*
* Note, that here we try to apply DTD defaults
XML_PARSE_NOENT | XML_PARSE_DTDATTR
| (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS));
if (doc == NULL || xmlerrcxt->err_occurred)
- xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT,
- "invalid XML document");
+ {
+ /* Use original option to decide which error code to throw */
+ if (xmloption_arg == XMLOPTION_DOCUMENT)
+ xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT,
+ "invalid XML document");
+ else
+ xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_CONTENT,
+ "invalid XML content");
+ }
}
else
{
- int res_code;
- size_t count;
- xmlChar *version;
- int standalone;
-
- res_code = parse_xml_decl(utf8string,
- &count, &version, NULL, &standalone);
- if (res_code != 0)
- xml_ereport_by_code(ERROR, ERRCODE_INVALID_XML_CONTENT,
- "invalid XML content: invalid XML declaration",
- res_code);
-
doc = xmlNewDoc(version);
Assert(doc->encoding == NULL);
doc->encoding = xmlStrdup((const xmlChar *) "UTF-8");
DETAIL: line 1: Start tag expected, '<' not found
bad
^
+ERROR: invalid XML document
+ ^
+DETAIL: line 1: Extra content at the end of the document
+ ^
SET XML OPTION CONTENT;
EXECUTE foo ('');
xmlconcat
good
(1 row)
+ xml
+--------------------------------------------------------------------
+(1 row)
+
+ xml
+------------------------------
+(1 row)
+
+ xml
+------------------
+(1 row)
+
+ERROR: invalid XML content
+LINE 1: SELECT xml ' oops
';
+ ^
+DETAIL: line 1: StartTag: invalid element name
+ ^
+ERROR: invalid XML content
+ ^
+DETAIL: line 1: StartTag: invalid element name
+ ^
+ERROR: invalid XML content
+ ^
+DETAIL: line 1: Extra content at the end of the document
+ ^
-- Test backwards parsing
CREATE VIEW xmlview1 AS SELECT xmlcomment('test');
CREATE VIEW xmlview2 AS SELECT xmlconcat('hello', 'you');