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 a9aa9d84 Misc fixes (#170)
a9aa9d84 is described below

commit a9aa9d84539c00be3b2fab684434e1c1ccfdef13
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Sep 24 11:18:20 2026 +0100

    Misc fixes (#170)
---
 .../schema/docpath/XmlSchemaElementValidator.java  |   8 ++
 .../ws/commons/schema/walker/XmlSchemaScope.java   |  23 +++-
 .../schema/docpath/TestPathFinderFailureTypes.java |  11 ++
 .../walker/ComplexContentExtensionWalkerTest.java  | 129 +++++++++++++++++++++
 4 files changed, 168 insertions(+), 3 deletions(-)

diff --git 
a/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/docpath/XmlSchemaElementValidator.java
 
b/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/docpath/XmlSchemaElementValidator.java
index 11e2c836..3efeaa57 100644
--- 
a/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/docpath/XmlSchemaElementValidator.java
+++ 
b/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/docpath/XmlSchemaElementValidator.java
@@ -144,6 +144,14 @@ final class XmlSchemaElementValidator {
                 continue;
             }
 
+            /*
+             * An attribute declared without a type is an xs:anySimpleType,
+             * which accepts any value; the walker leaves its type unset.
+             */
+            if (attribute.getType() == null) {
+                continue;
+            }
+
             if 
(attribute.getType().getType().equals(XmlSchemaTypeInfo.Type.COMPLEX)) {
 
                 throw new ValidationException("Attribute " + attrQName + " of 
element " + elemQName
diff --git 
a/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
 
b/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
index 1fcb5592..08be6e43 100644
--- 
a/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
+++ 
b/xmlschema-walker/src/main/java/org/apache/ws/commons/schema/walker/XmlSchemaScope.java
@@ -403,6 +403,14 @@ final class XmlSchemaScope {
                 child = baseParticle;
             } else if (baseParticle == null) {
                 child = ext.getParticle();
+            } else if (!(baseParticle instanceof XmlSchemaSequenceMember)
+                       || !(ext.getParticle() instanceof 
XmlSchemaSequenceMember)) {
+                // Only an xs:all is not a sequence member, and XML Schema 1.0
+                // does not allow one to be combined with any other particle.
+                throw new XmlSchemaException("An extension of " + 
ext.getBaseTypeName()
+                                             + " adds content to it, but one 
of the two content"
+                                             + " models is an xs:all group, 
which cannot be"
+                                             + " combined with other 
particles.");
             } else {
                 XmlSchemaSequence seq = new XmlSchemaSequence();
                 seq.getItems().add((XmlSchemaSequenceMember)baseParticle);
@@ -420,8 +428,13 @@ final class XmlSchemaScope {
             } else if (ext.getAnyAttribute() == null) {
                 anyAttr = baseAnyAttr;
             } else {
-                String[] baseNamespaces = baseAnyAttr.getNamespace().split(" 
");
-                String[] childNamespaces = 
ext.getAnyAttribute().getNamespace().split(" ");
+                // An absent namespace attribute means ##any, and a union with
+                // ##any is ##any.
+                final String baseNamespace = baseAnyAttr.getNamespace();
+                final String childNamespace = 
ext.getAnyAttribute().getNamespace();
+                final boolean unionIsAny = isAnyNamespace(baseNamespace) || 
isAnyNamespace(childNamespace);
+                String[] baseNamespaces = unionIsAny ? new String[0] : 
baseNamespace.split(" ");
+                String[] childNamespaces = unionIsAny ? new String[0] : 
childNamespace.split(" ");
 
                 HashSet<String> namespaces = new HashSet<String>();
                 for (String baseNs : baseNamespaces) {
@@ -441,7 +454,7 @@ final class XmlSchemaScope {
                 }
 
                 anyAttr = new XmlSchemaAnyAttribute();
-                anyAttr.setNamespace(nsAsString.toString());
+                anyAttr.setNamespace(unionIsAny ? "##any" : 
nsAsString.toString());
                 
anyAttr.setProcessContent(ext.getAnyAttribute().getProcessContent());
                 anyAttr.setAnnotation(ext.getAnyAttribute().getAnnotation());
                 anyAttr.setId(ext.getAnyAttribute().getId());
@@ -825,6 +838,10 @@ final class XmlSchemaScope {
         return (parent == null) ? null : parent.getUserRecognizedType();
     }
 
+    private static boolean isAnyNamespace(String namespace) {
+        return (namespace == null) || "##any".equals(namespace.trim());
+    }
+
     private static String getName(XmlSchemaNamed name, String defaultName) {
         if (name.isAnonymous()) {
             return defaultName;
diff --git 
a/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/TestPathFinderFailureTypes.java
 
b/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/TestPathFinderFailureTypes.java
index 7aaec5c0..06a96cda 100644
--- 
a/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/TestPathFinderFailureTypes.java
+++ 
b/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/docpath/TestPathFinderFailureTypes.java
@@ -136,6 +136,17 @@ public class TestPathFinderFailureTypes extends Assert {
         }
     }
 
+    /**
+     * An attribute declared without a type is an xs:anySimpleType and accepts 
any value.
+     */
+    @Test
+    public void testUntypedAttributeAcceptsAnyValue() throws Exception {
+        walk("<xs:element name=\"root\"><xs:complexType>"
+             + "<xs:attribute name=\"x\"/>"
+             + "</xs:complexType></xs:element>",
+             "<root xmlns=\"urn:t\" x=\"1\"/>");
+    }
+
     @Test
     public void testValidDocumentStillWalks() throws Exception {
         walk("<xs:simpleType name=\"s\"><xs:restriction base=\"xs:string\">"
diff --git 
a/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/walker/ComplexContentExtensionWalkerTest.java
 
b/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/walker/ComplexContentExtensionWalkerTest.java
new file mode 100644
index 00000000..2d9faecf
--- /dev/null
+++ 
b/xmlschema-walker/src/test/java/org/apache/ws/commons/schema/walker/ComplexContentExtensionWalkerTest.java
@@ -0,0 +1,129 @@
+/**
+ * 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 org.apache.ws.commons.schema.walker;
+
+import java.io.StringReader;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.ws.commons.schema.XmlSchemaAnyAttribute;
+import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * A complex content extension combines the content model and attribute 
wildcard of its base
+ * with its own. Doing so must not escape as a ClassCastException or 
NullPointerException.
+ */
+public class ComplexContentExtensionWalkerTest extends Assert {
+
+    private static List<String> walkRoot(String body) {
+        XmlSchemaCollection collection = new XmlSchemaCollection();
+        collection.read(new StringReader(
+            "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"; 
xmlns:tns=\"urn:ext\""
+            + " targetNamespace=\"urn:ext\" elementFormDefault=\"qualified\">"
+            + body
+            + "</xs:schema>"));
+        XmlSchemaElement root = collection.getElementByQName(new 
QName("urn:ext", "root"));
+        assertNotNull("the schema under test must declare a 'root' element", 
root);
+
+        // Records the namespace of every attribute wildcard visited.
+        final List<String> anyAttributeNamespaces = new ArrayList<String>();
+        XmlSchemaVisitor visitor = (XmlSchemaVisitor)Proxy.newProxyInstance(
+            XmlSchemaVisitor.class.getClassLoader(), new Class<?>[] 
{XmlSchemaVisitor.class},
+            (proxy, method, args) -> {
+                if ("onVisitAnyAttribute".equals(method.getName())) {
+                    
anyAttributeNamespaces.add(((XmlSchemaAnyAttribute)args[1]).getNamespace());
+                }
+                return null;
+            });
+        new XmlSchemaWalker(collection, visitor).walk(root);
+        return anyAttributeNamespaces;
+    }
+
+    @Test
+    public void testExtendingAnAllGroupWithMoreContentIsRejected() {
+        try {
+            walkRoot("<xs:complexType name=\"base\"><xs:all>"
+                     + "<xs:element name=\"a\" type=\"xs:string\"/>"
+                     + "</xs:all></xs:complexType>"
+                     + "<xs:complexType name=\"derived\"><xs:complexContent>"
+                     + "<xs:extension base=\"tns:base\"><xs:sequence>"
+                     + "<xs:element name=\"b\" type=\"xs:string\"/>"
+                     + 
"</xs:sequence></xs:extension></xs:complexContent></xs:complexType>"
+                     + "<xs:element name=\"root\" type=\"tns:derived\"/>");
+            fail("expected an xs:all combined with other content to be 
rejected");
+        } catch (XmlSchemaException expected) {
+            assertTrue(expected.getMessage(), 
expected.getMessage().contains("xs:all"));
+        }
+    }
+
+    @Test
+    public void testExtendingASequenceWithASequenceStillWalks() {
+        walkRoot("<xs:complexType name=\"base\"><xs:sequence>"
+                 + "<xs:element name=\"a\" type=\"xs:string\"/>"
+                 + "</xs:sequence></xs:complexType>"
+                 + "<xs:complexType name=\"derived\"><xs:complexContent>"
+                 + "<xs:extension base=\"tns:base\"><xs:sequence>"
+                 + "<xs:element name=\"b\" type=\"xs:string\"/>"
+                 + 
"</xs:sequence></xs:extension></xs:complexContent></xs:complexType>"
+                 + "<xs:element name=\"root\" type=\"tns:derived\"/>");
+    }
+
+    /**
+     * An xs:anyAttribute with no namespace attribute allows any namespace, 
and so does its union
+     * with any other wildcard.
+     */
+    @Test
+    public void testAnyAttributeWithoutANamespaceIsAnyNamespace() {
+        List<String> namespaces =
+            walkRoot("<xs:complexType name=\"base\"><xs:sequence/>"
+                     + "<xs:anyAttribute/></xs:complexType>"
+                     + "<xs:complexType name=\"derived\"><xs:complexContent>"
+                     + "<xs:extension base=\"tns:base\">"
+                     + "<xs:anyAttribute namespace=\"urn:other\" 
processContents=\"lax\"/>"
+                     + "</xs:extension></xs:complexContent></xs:complexType>"
+                     + "<xs:element name=\"root\" type=\"tns:derived\"/>");
+        assertEquals(1, namespaces.size());
+        assertEquals("##any", namespaces.get(0));
+    }
+
+    @Test
+    public void testAnyAttributeNamespacesAreStillUnited() {
+        List<String> namespaces =
+            walkRoot("<xs:complexType name=\"base\"><xs:sequence/>"
+                     + "<xs:anyAttribute 
namespace=\"urn:a\"/></xs:complexType>"
+                     + "<xs:complexType name=\"derived\"><xs:complexContent>"
+                     + "<xs:extension base=\"tns:base\">"
+                     + "<xs:anyAttribute namespace=\"urn:b\"/>"
+                     + "</xs:extension></xs:complexContent></xs:complexType>"
+                     + "<xs:element name=\"root\" type=\"tns:derived\"/>");
+        assertEquals(1, namespaces.size());
+        String[] united = namespaces.get(0).trim().split(" ");
+        Arrays.sort(united);
+        assertArrayEquals(new String[] {"urn:a", "urn:b"}, united);
+    }
+}

Reply via email to