diff --git a/exist-core/pom.xml b/exist-core/pom.xml
index 33b050d2cb..1121c8ea59 100644
--- a/exist-core/pom.xml
+++ b/exist-core/pom.xml
@@ -732,6 +732,7 @@
src/test/resources/standalone-webapp/WEB-INF/web.xml
src/test/xquery/maps/maps.xqm
src/test/xquery/util/util.xml
+ src/test/xquery/xquery3/parse-xml.xqm
src/test/xquery/xquery3/serialize.xql
src/main/java/org/exist/Indexer.java
src/main/resources-filtered/org/exist/system.properties
@@ -945,6 +946,7 @@
src/test/xquery/maps/maps.xqm
src/test/xquery/securitymanager/acl.xqm
src/test/xquery/util/util.xml
+ src/test/xquery/xquery3/parse-xml.xqm
src/test/xquery/xquery3/postfix-expr.xqm
src/test/xquery/xquery3/serialize.xql
src/main/java/org/exist/Indexer.java
diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java
index 2c475c027d..b8096a6742 100644
--- a/exist-core/src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java
+++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java
@@ -64,7 +64,6 @@
import java.io.IOException;
import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
import static org.exist.util.ByteOrderMark.stripXmlBom;
@@ -104,10 +103,6 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
return Sequence.EMPTY_SEQUENCE;
}
final String xmlContent = args[0].itemAt(0).getStringValue();
- if (xmlContent.isEmpty()) {
- return Sequence.EMPTY_SEQUENCE;
- }
-
return parse(xmlContent, args);
}
@@ -134,7 +129,27 @@ private ValidationReport validate(String xmlContent, final SAXAdapter saxAdapter
xmlContent = stripXmlBom(xmlContent);
final String xml;
if (isCalledAs("parse-xml-fragment")) {
- xml = "<" + FRAGMENT_WRAPPER_NAME + ">" + xmlContent + "" + FRAGMENT_WRAPPER_NAME + ">";
+ String declStr = xmlContent.toLowerCase();
+ final int startIdx = declStr.indexOf(" -1) {
+
+ // NOTE(AR) for parsing fragments the input must be an external entity, so validate that the declaration is a TextDecl (https://www.w3.org/TR/REC-xml/#NT-TextDecl) and not a full XMLDecl (https://www.w3.org/TR/REC-xml/#NT-XMLDecl) with standalone attribute
+
+ declStr = declStr.substring(startIdx);
+ int endIdx = declStr.indexOf("?>");
+ if (endIdx > -1) {
+ endIdx += 2;
+ }
+ declStr = declStr.substring(0, endIdx);
+ if (declStr.contains("standalone=")) {
+ throw new XPathException(this, ErrorCodes.FODC0006, "Input to fn:parse-xml-fragment must be a valid external entity, but 'standalone' attribute was detected in the declaration");
+ }
+
+ xml = xmlContent;
+
+ } else {
+ xml = "<" + FRAGMENT_WRAPPER_NAME + ">" + xmlContent + "" + FRAGMENT_WRAPPER_NAME + ">";
+ }
} else {
xml = xmlContent;
}
diff --git a/exist-core/src/test/xquery/xquery3/parse-xml.xq b/exist-core/src/test/xquery/xquery3/parse-xml.xq
deleted file mode 100644
index ab920bef04..0000000000
--- a/exist-core/src/test/xquery/xquery3/parse-xml.xq
+++ /dev/null
@@ -1,40 +0,0 @@
-(:
- : eXist-db Open Source Native XML Database
- : Copyright (C) 2001 The eXist-db Authors
- :
- : info@exist-db.org
- : http://www.exist-db.org
- :
- : This library is free software; you can redistribute it and/or
- : modify it under the terms of the GNU Lesser General Public
- : License as published by the Free Software Foundation; either
- : version 2.1 of the License, or (at your option) any later version.
- :
- : This library is distributed in the hope that it will be useful,
- : but WITHOUT ANY WARRANTY; without even the implied warranty of
- : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- : Lesser General Public License for more details.
- :
- : You should have received a copy of the GNU Lesser General Public
- : License along with this library; if not, write to the Free Software
- : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- :)
-xquery version "3.0";
-
-(:~ Additional tests for the fn:parse-xml and fn:parse-xml-fragment functions :)
-module namespace px="http://exist-db.org/xquery/test/parse-xml";
-
-declare namespace test="http://exist-db.org/xquery/xqsuite";
-
-declare
- %test:assertTrue
-function px:fragment-type() {
- fn:parse-xml-fragment("He was so kind") instance of document-node()
-};
-
-
-declare
- %test:assertEquals(3)
-function px:fragment-count() {
- count(parse-xml-fragment("He was so kind")/node())
-};
diff --git a/exist-core/src/test/xquery/xquery3/parse-xml.xqm b/exist-core/src/test/xquery/xquery3/parse-xml.xqm
new file mode 100644
index 0000000000..3e39320490
--- /dev/null
+++ b/exist-core/src/test/xquery/xquery3/parse-xml.xqm
@@ -0,0 +1,147 @@
+(:
+ : Elemental
+ : Copyright (C) 2024, Evolved Binary Ltd
+ :
+ : admin@evolvedbinary.com
+ : https://www.evolvedbinary.com | https://www.elemental.xyz
+ :
+ : This library is free software; you can redistribute it and/or
+ : modify it under the terms of the GNU Lesser General Public
+ : License as published by the Free Software Foundation; version 2.1.
+ :
+ : This library is distributed in the hope that it will be useful,
+ : but WITHOUT ANY WARRANTY; without even the implied warranty of
+ : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ : Lesser General Public License for more details.
+ :
+ : You should have received a copy of the GNU Lesser General Public
+ : License along with this library; if not, write to the Free Software
+ : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ :
+ : NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ : The original license header is included below.
+ :
+ : =====================================================================
+ :
+ : eXist-db Open Source Native XML Database
+ : Copyright (C) 2001 The eXist-db Authors
+ :
+ : info@exist-db.org
+ : http://www.exist-db.org
+ :
+ : This library is free software; you can redistribute it and/or
+ : modify it under the terms of the GNU Lesser General Public
+ : License as published by the Free Software Foundation; either
+ : version 2.1 of the License, or (at your option) any later version.
+ :
+ : This library is distributed in the hope that it will be useful,
+ : but WITHOUT ANY WARRANTY; without even the implied warranty of
+ : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ : Lesser General Public License for more details.
+ :
+ : You should have received a copy of the GNU Lesser General Public
+ : License along with this library; if not, write to the Free Software
+ : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ :)
+xquery version "3.0";
+
+(:~ Additional tests for the fn:parse-xml and fn:parse-xml-fragment functions :)
+module namespace px="http://exist-db.org/xquery/test/parse-xml";
+
+declare namespace test="http://exist-db.org/xquery/xqsuite";
+
+declare
+ %test:assertEmpty
+function px:fragment-type-1() {
+ fn:parse-xml-fragment(())
+};
+
+declare
+ %test:assertTrue
+function px:fragment-type-2() {
+ fn:parse-xml-fragment("") instance of document-node()
+};
+
+declare
+ %test:assertEmpty
+function px:fragment-children-1() {
+ fn:parse-xml-fragment("")/node()
+};
+
+declare
+ %test:assertTrue
+function px:fragment-type-3() {
+ fn:parse-xml-fragment(" ") instance of document-node()
+};
+
+declare
+ %test:assertTrue(" ")
+function px:fragment-children-2() {
+ fn:parse-xml-fragment(" ")/node()
+};
+
+declare
+ %test:assertTrue
+function px:fragment-type-4() {
+ fn:parse-xml-fragment("abcdabcd") instance of document-node()
+};
+
+declare
+ %test:assertEquals("abcd", "abcd")
+function px:fragment-children-3() {
+ fn:parse-xml-fragment("abcdabcd")/node()
+};
+
+declare
+ %test:assertTrue
+function px:fragment-type-5() {
+ fn:parse-xml-fragment("He was so kind") instance of document-node()
+};
+
+declare
+ %test:assertEquals(1)
+function px:fragment-count() {
+ count(parse-xml-fragment("He was so kind"))
+};
+
+declare
+ %test:assertEquals(3)
+function px:fragment-node-count() {
+ count(parse-xml-fragment("He was so kind")/node())
+};
+
+declare
+ %test:assertTrue
+function px:fragment-xml-decl() {
+ fn:parse-xml-fragment('') instance of document-node()
+};
+
+declare
+ %test:assertError("FODC0006")
+function px:fragment-xml-decl-standalone-yes() {
+ fn:parse-xml-fragment('')
+};
+
+declare
+ %test:assertError("FODC0006")
+function px:fragment-xml-decl-standalone-no() {
+ fn:parse-xml-fragment('')
+};
+
+declare
+ %test:assertTrue
+function px:fragment-xml-decl-encoding() {
+ fn:parse-xml-fragment('') instance of document-node()
+};
+
+declare
+ %test:assertError("FODC0006")
+function px:fragment-xml-decl-encoding-standalone-yes() {
+ fn:parse-xml-fragment('')
+};
+
+declare
+ %test:assertError("FODC0006")
+function px:fragment-xml-decl-encoding-standalone-no() {
+ fn:parse-xml-fragment('')
+};