This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-xmlschema.git
The following commit(s) were added to refs/heads/master by this push:
new c3c458f3 Collect ancestor prefix declarations without recursion (#169)
c3c458f3 is described below
commit c3c458f394c574dcd7dac941ecbad5ead2cde197
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Sep 24 11:07:00 2026 +0100
Collect ancestor prefix declarations without recursion (#169)
---
.../ws/commons/schema/utils/PrefixCollector.java | 17 ++++++---
.../src/test/java/tests/NestingDepthLimitTest.java | 40 ++++++++++++++++++++++
2 files changed, 53 insertions(+), 4 deletions(-)
diff --git
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/utils/PrefixCollector.java
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/utils/PrefixCollector.java
index f5bec260..3320b23c 100644
---
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/utils/PrefixCollector.java
+++
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/utils/PrefixCollector.java
@@ -19,6 +19,9 @@
package org.apache.ws.commons.schema.utils;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
@@ -59,12 +62,18 @@ public abstract class PrefixCollector {
* Searches for namespace prefix declarations in the given node. For any
prefix declaration, it invokes
* {@link #declare(String, String)}. This method works recursively: The
parent nodes prefix declarations
* are collected before the current nodes.
+ * <p>
+ * The ancestors are walked with a loop rather than by recursion, as a
schema element embedded
+ * deep in a larger document would otherwise take one stack frame per
ancestor.
+ * </p>
*/
public void searchAllPrefixDeclarations(Node pNode) {
- Node parent = pNode.getParentNode();
- if (parent != null) {
- searchAllPrefixDeclarations(parent);
+ Deque<Node> ancestry = new ArrayDeque<Node>();
+ for (Node node = pNode; node != null; node = node.getParentNode()) {
+ ancestry.push(node);
+ }
+ while (!ancestry.isEmpty()) {
+ searchLocalPrefixDeclarations(ancestry.pop());
}
- searchLocalPrefixDeclarations(pNode);
}
}
diff --git a/xmlschema-core/src/test/java/tests/NestingDepthLimitTest.java
b/xmlschema-core/src/test/java/tests/NestingDepthLimitTest.java
index e9c70811..de91c742 100644
--- a/xmlschema-core/src/test/java/tests/NestingDepthLimitTest.java
+++ b/xmlschema-core/src/test/java/tests/NestingDepthLimitTest.java
@@ -24,6 +24,9 @@ import java.io.FileWriter;
import java.io.StringReader;
import java.io.Writer;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaException;
@@ -33,6 +36,8 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.xml.sax.InputSource;
/**
@@ -153,6 +158,41 @@ public class NestingDepthLimitTest extends Assert {
assertNotNull(schema);
}
+ /**
+ * read(Element) collects the namespace declarations of every ancestor of
the
+ * schema element, which must not take a stack frame per ancestor when the
+ * schema is embedded deep in a larger document such as a WSDL. The prefix
+ * declared on the outermost wrapper must still be seen.
+ */
+ @Test
+ public void testSchemaEmbeddedDeepInADocumentStillParses() throws
Exception {
+ int depth = 20000;
+ StringBuilder doc = new StringBuilder();
+ doc.append("<w xmlns:tns=\"urn:embedded\">");
+ for (int i = 1; i < depth; i++) {
+ doc.append("<w>");
+ }
+ doc.append("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"")
+ .append(" targetNamespace=\"urn:embedded\">")
+ .append("<xs:complexType name=\"t\"/>")
+ .append("<xs:element name=\"e\" type=\"tns:t\"/>")
+ .append("</xs:schema>");
+ for (int i = 0; i < depth; i++) {
+ doc.append("</w>");
+ }
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ Document document = factory.newDocumentBuilder()
+ .parse(new InputSource(new StringReader(doc.toString())));
+ Element schemaElement = (Element)document
+ .getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema",
"schema").item(0);
+
+ XmlSchema schema = new XmlSchemaCollection().read(schemaElement);
+ assertEquals(new QName("urn:embedded", "t"),
+ schema.getElementByName("e").getSchemaTypeName());
+ }
+
private void assertMarkupRejected(String kind) {
XmlSchemaCollection collection = new XmlSchemaCollection();
try {