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 69446f00 Keep complexType block, union members and keyref refer 
through read and write (#174)
69446f00 is described below

commit 69446f006576e4698b8b305851acb66ccf218245
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Sep 24 12:29:13 2026 +0100

    Keep complexType block, union members and keyref refer through read and 
write (#174)
---
 .../apache/ws/commons/schema/SchemaBuilder.java    |  13 +-
 .../ws/commons/schema/XmlSchemaSerializer.java     |   6 +-
 .../src/test/java/tests/SchemaRoundTripTest.java   | 151 +++++++++++++++++++++
 3 files changed, 159 insertions(+), 11 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 0009c03a..c4ff118e 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
@@ -545,11 +545,9 @@ public class SchemaBuilder {
         keyrefEl = XDOMUtil.getFirstChildElementNS(el, XmlSchema.SCHEMA_NS, 
"keyref");
         if (keyrefEl != null) {
             while (keyrefEl != null) {
+                // handleConstraint resolves "refer" against the keyref's own 
namespace
+                // declarations, which may differ from those of the enclosing 
element.
                 XmlSchemaKeyref keyRef = 
(XmlSchemaKeyref)handleConstraint(keyrefEl, XmlSchemaKeyref.class);
-                if (keyrefEl.hasAttribute("refer")) {
-                    String name = keyrefEl.getAttribute("refer");
-                    keyRef.refer = getRefQName(name, el);
-                }
                 element.getConstraints().add(keyRef);
                 keyrefEl = XDOMUtil.getNextSiblingElementNS(keyrefEl, 
XmlSchema.SCHEMA_NS, "keyref");
             }
@@ -1974,12 +1972,11 @@ public class SchemaBuilder {
 
             XmlSchemaSimpleType unionSimpleType = handleSimpleType(schema, 
inlineUnionType, schemaEl, false);
 
+            // An inline member is one of the base types, not a memberTypes 
reference: a local
+            // simple type cannot be referred to by name, and naming it again 
in memberTypes
+            // made the serializer write it back twice.
             union.getBaseTypes().add(unionSimpleType);
 
-            if (!unionSimpleType.isAnonymous()) {
-                union.setMemberTypesSource(union.getMemberTypesSource() + " " 
+ unionSimpleType.getName());
-            }
-
             inlineUnionType =
                 XDOMUtil.getNextSiblingElementNS(inlineUnionType, 
XmlSchema.SCHEMA_NS, "simpleType");
         }
diff --git 
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
 
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
index 76f60f6b..e1f358c5 100644
--- 
a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
+++ 
b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java
@@ -981,7 +981,7 @@ public class XmlSchemaSerializer {
 
         if (complexTypeObj.getBlock() != null
             && complexTypeObj.getBlock() != XmlSchemaDerivationMethod.NONE) {
-            serializedComplexType.setAttributeNS(null, "block", 
complexTypeObj.toString());
+            serializedComplexType.setAttributeNS(null, "block", 
complexTypeObj.getBlock().toString());
         }
 
         if (complexTypeObj.getFinalDerivation() != null
@@ -2199,8 +2199,8 @@ public class XmlSchemaSerializer {
             union.setAttributeNS(null, "id", unionObj.getId());
         }
 
-        if (unionObj.getMemberTypesSource() != null) {
-            QName[] memberTypesQNames = unionObj.getMemberTypesQNames();       
     
+        if (unionObj.getMemberTypesSource() != null && 
unionObj.getMemberTypesQNames() != null) {
+            QName[] memberTypesQNames = unionObj.getMemberTypesQNames();
             for (QName qn : memberTypesQNames) {
                 String namespace = qn.getNamespaceURI();
                 if (namespace.length() != 0 && qn.getPrefix().length() != 0) {
diff --git a/xmlschema-core/src/test/java/tests/SchemaRoundTripTest.java 
b/xmlschema-core/src/test/java/tests/SchemaRoundTripTest.java
new file mode 100644
index 00000000..2f1720b4
--- /dev/null
+++ b/xmlschema-core/src/test/java/tests/SchemaRoundTripTest.java
@@ -0,0 +1,151 @@
+/**
+ * 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 javax.xml.namespace.QName;
+
+import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.XmlSchemaComplexType;
+import org.apache.ws.commons.schema.XmlSchemaDerivationMethod;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaIdentityConstraint;
+import org.apache.ws.commons.schema.XmlSchemaKeyref;
+import org.apache.ws.commons.schema.XmlSchemaSimpleType;
+import org.apache.ws.commons.schema.XmlSchemaSimpleTypeUnion;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * A schema read, written and read again must mean what it meant the first 
time.
+ */
+public class SchemaRoundTripTest extends Assert {
+
+    private static XmlSchema read(String schema) {
+        return new XmlSchemaCollection().read(new StringReader(schema));
+    }
+
+    private static XmlSchema roundTrip(XmlSchema schema) throws Exception {
+        StringWriter written = new StringWriter();
+        schema.write(written);
+        return read(written.toString());
+    }
+
+    /**
+     * block was written as the type's toString(), and so read back as no 
constraint at all.
+     */
+    @Test
+    public void testComplexTypeBlockIsKept() throws Exception {
+        XmlSchema schema = roundTrip(read(
+            "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"; 
targetNamespace=\"urn:t\">"
+            + "<xs:complexType name=\"Account\" block=\"#all\"/>"
+            + "<xs:complexType name=\"Partial\" block=\"extension\"/>"
+            + "</xs:schema>"));
+
+        XmlSchemaDerivationMethod all =
+            ((XmlSchemaComplexType)schema.getTypeByName(new QName("urn:t", 
"Account"))).getBlock();
+        assertTrue(all.isAll());
+        XmlSchemaDerivationMethod partial =
+            ((XmlSchemaComplexType)schema.getTypeByName(new QName("urn:t", 
"Partial"))).getBlock();
+        assertTrue(partial.isExtension());
+        assertFalse(partial.isRestriction());
+    }
+
+    private static XmlSchemaSimpleTypeUnion union(XmlSchema schema) {
+        return (XmlSchemaSimpleTypeUnion)((XmlSchemaSimpleType)schema
+            .getTypeByName(new QName("urn:t", "u"))).getContent();
+    }
+
+    /**
+     * A named simple type inside a union was added to memberTypes as well as 
being an inline
+     * member: with no memberTypes attribute write() then threw a 
NullPointerException, and with
+     * one the member was written back twice.
+     */
+    @Test
+    public void testNamedInlineUnionMemberWithoutMemberTypes() throws 
Exception {
+        XmlSchema schema = read(
+            "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"; 
targetNamespace=\"urn:t\">"
+            + "<xs:simpleType name=\"u\"><xs:union>"
+            + "<xs:simpleType name=\"n\"><xs:restriction 
base=\"xs:string\"/></xs:simpleType>"
+            + "</xs:union></xs:simpleType></xs:schema>");
+        assertNull(union(schema).getMemberTypesSource());
+
+        XmlSchemaSimpleTypeUnion reread = union(roundTrip(schema));
+        assertNull(reread.getMemberTypesQNames());
+        assertEquals(1, reread.getBaseTypes().size());
+    }
+
+    @Test
+    public void testNamedInlineUnionMemberWithMemberTypes() throws Exception {
+        XmlSchema schema = read(
+            "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"; 
targetNamespace=\"urn:t\">"
+            + "<xs:simpleType name=\"u\"><xs:union memberTypes=\"xs:int\">"
+            + "<xs:simpleType name=\"n\"><xs:restriction 
base=\"xs:string\"/></xs:simpleType>"
+            + "</xs:union></xs:simpleType></xs:schema>");
+
+        XmlSchemaSimpleTypeUnion reread = union(roundTrip(schema));
+        assertArrayEquals(new QName[] {new 
QName("http://www.w3.org/2001/XMLSchema";, "int")},
+                          reread.getMemberTypesQNames());
+        assertEquals(1, reread.getBaseTypes().size());
+    }
+
+    private static QName refer(XmlSchema schema) {
+        XmlSchemaElement root = schema.getElementByName(new QName("urn:B", 
"root"));
+        for (XmlSchemaIdentityConstraint constraint : root.getConstraints()) {
+            if (constraint instanceof XmlSchemaKeyref) {
+                return ((XmlSchemaKeyref)constraint).getRefer();
+            }
+        }
+        fail("no keyref");
+        return null;
+    }
+
+    private static String keyrefSchema(String outerDeclaration) {
+        return "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""; + 
outerDeclaration
+               + " targetNamespace=\"urn:B\">"
+               + "<xs:element name=\"root\"><xs:complexType><xs:sequence>"
+               + "<xs:element name=\"i\" type=\"xs:string\" 
maxOccurs=\"unbounded\"/>"
+               + "</xs:sequence></xs:complexType>"
+               + "<xs:key name=\"k\"><xs:selector xpath=\"i\"/><xs:field 
xpath=\".\"/></xs:key>"
+               + "<xs:keyref name=\"r\" refer=\"p:k\" xmlns:p=\"urn:B\">"
+               + "<xs:selector xpath=\"i\"/><xs:field 
xpath=\".\"/></xs:keyref>"
+               + "</xs:element></xs:schema>";
+    }
+
+    /**
+     * refer is resolved against the keyref's own namespace declarations; it 
used to be resolved
+     * again against the enclosing element's, which here bind p to a different 
namespace.
+     */
+    @Test
+    public void testKeyrefReferUsesItsOwnDeclarations() throws Exception {
+        XmlSchema schema = read(keyrefSchema(" xmlns:p=\"urn:A\""));
+        assertEquals(new QName("urn:B", "k"), refer(schema));
+        assertEquals(new QName("urn:B", "k"), refer(roundTrip(schema)));
+    }
+
+    @Test
+    public void testKeyrefReferDeclaredOnlyOnTheKeyref() throws Exception {
+        assertEquals(new QName("urn:B", "k"), refer(read(keyrefSchema(""))));
+    }
+}

Reply via email to