This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/foreign in repository https://gitbox.apache.org/repos/asf/ws-xmlschema.git
commit a85b5ce37c369e97919c447139e03a38eeafd21c Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Thu Sep 17 10:17:04 2026 +0100 Stop capturing foreign children of the document element --- .../apache/ws/commons/schema/SchemaBuilder.java | 19 +++- .../java/tests/ForeignTopLevelContentTest.java | 105 +++++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/SchemaBuilder.java b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/SchemaBuilder.java index 5c57d6af..e7609d9f 100644 --- a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/SchemaBuilder.java +++ b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/SchemaBuilder.java @@ -737,7 +737,7 @@ public class SchemaBuilder { } // add the extensibility components - processExtensibilityComponents(currentSchema, schemaEl, false); + processExtensibilityComponents(currentSchema, schemaEl, false, false); return currentSchema; } @@ -1982,6 +1982,21 @@ public class SchemaBuilder { private void processExtensibilityComponents(XmlSchemaObject schemaObject, Element parentElement, boolean namespaces) { + processExtensibilityComponents(schemaObject, parentElement, namespaces, true); + } + + /** + * @param childElements whether foreign-namespace child elements are captured as well as + * foreign attributes. False for the document element: xs:schema permits foreign + * attributes but no foreign children, and a document reached through a + * schemaLocation is whatever was at that URL. Capturing its children put the + * contents of any XML file into the model, which the serializer then wrote back + * out - so an embedding that republishes resolved schemas handed them back. + */ + private void processExtensibilityComponents(XmlSchemaObject schemaObject, + Element parentElement, + boolean namespaces, + boolean childElements) { if (extReg != null) { // process attributes @@ -2003,7 +2018,7 @@ public class SchemaBuilder { } // process elements - Node child = parentElement.getFirstChild(); + Node child = childElements ? parentElement.getFirstChild() : null; while (child != null) { if (child.getNodeType() == Node.ELEMENT_NODE) { Element extElement = (Element)child; diff --git a/xmlschema-core/src/test/java/tests/ForeignTopLevelContentTest.java b/xmlschema-core/src/test/java/tests/ForeignTopLevelContentTest.java new file mode 100644 index 00000000..a2d4cb17 --- /dev/null +++ b/xmlschema-core/src/test/java/tests/ForeignTopLevelContentTest.java @@ -0,0 +1,105 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package tests; + +import java.io.StringReader; +import java.io.StringWriter; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.resolver.URIResolver; + +import org.junit.Assert; +import org.junit.Test; +import org.xml.sax.InputSource; + +/** + * A document reached through a schemaLocation is whatever was at that URL, and any XML root + * parses as a schema. Its foreign children must not be captured into the model, or an + * embedding that republishes resolved schemas hands the fetched file's contents back. + */ +public class ForeignTopLevelContentTest extends Assert { + + private static final String SECRET = "TOP-SECRET-VALUE"; + + private static final String NOT_A_SCHEMA = + "<config targetNamespace=\"urn:internal\" xmlns=\"urn:internal\">" + + "<dbPassword>" + SECRET + "</dbPassword>" + + "</config>"; + + private static String republish(XmlSchema schema) throws Exception { + StringWriter writer = new StringWriter(); + schema.write(writer); + return writer.toString(); + } + + @Test + public void testForeignChildrenOfTheRootAreNotRepublished() throws Exception { + XmlSchema schema = new XmlSchemaCollection().read(new StringReader(NOT_A_SCHEMA)); + assertFalse("the fetched document's content must not reach the serializer", + republish(schema).contains(SECRET)); + } + + @Test + public void testForeignChildrenOfAnImportedDocumentAreNotRepublished() throws Exception { + XmlSchemaCollection collection = new XmlSchemaCollection(); + collection.setSchemaResolver(new URIResolver() { + public InputSource resolveEntity(String namespace, String schemaLocation, String baseUri) { + InputSource source = new InputSource(new StringReader(NOT_A_SCHEMA)); + source.setSystemId("http://example.invalid/" + schemaLocation); + return source; + } + }); + collection.read(new StringReader( + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"urn:a\">" + + "<xs:import namespace=\"urn:internal\" schemaLocation=\"config.xml\"/>" + + "</xs:schema>")); + + XmlSchema imported = collection.schemaForNamespace("urn:internal"); + assertNotNull(imported); + assertFalse(republish(imported).contains(SECRET)); + } + + /** Foreign attributes on xs:schema are legal, and are still captured. */ + @Test + public void testForeignAttributesOnTheRootAreStillCaptured() throws Exception { + XmlSchema schema = new XmlSchemaCollection().read(new StringReader( + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + + " xmlns:ext=\"http://customattrib.org\" ext:stamp=\"kept\"" + + " targetNamespace=\"urn:a\">" + + "<xs:element name=\"e\" type=\"xs:string\"/></xs:schema>")); + assertNotNull("a foreign attribute on xs:schema must still be captured", + schema.getMetaInfoMap()); + } + + /** Foreign children of a complexType or element are legal extension points and still work. */ + @Test + public void testForeignChildrenOfOtherComponentsAreStillCaptured() throws Exception { + XmlSchema schema = new XmlSchemaCollection().read(new StringReader( + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + + " xmlns:ext=\"http://customattrib.org\" targetNamespace=\"urn:a\">" + + "<xs:element name=\"e\" type=\"xs:string\">" + + "<ext:customElt prefix=\"ext\" suffix=\"elt\"/>" + + "</xs:element></xs:schema>")); + assertNotNull(schema.getElementByName("e")); + assertNotNull("extension elements on an xs:element must still be captured", + schema.getElementByName("e").getMetaInfoMap()); + } +}
