diff --git a/src/main/java/org/apache/xmlbeans/impl/validator/Validator.java b/src/main/java/org/apache/xmlbeans/impl/validator/Validator.java
index da7b8bfec..5ffeada18 100644
--- a/src/main/java/org/apache/xmlbeans/impl/validator/Validator.java
+++ b/src/main/java/org/apache/xmlbeans/impl/validator/Validator.java
@@ -373,7 +373,7 @@ private void beginEvent(Event event) {
}
if (elementType.blockExtension()) {
- for (SchemaType t = xsiType; !t.equals(elementType);
+ for (SchemaType t = xsiType; t != null && !t.equals(elementType);
t = t.getBaseType()) {
if (t.getDerivationType() == SchemaType.DT_EXTENSION) {
emitFieldError(event, XmlErrorCodes.ELEM_LOCALLY_VALID$XSI_TYPE_BLOCK_EXTENSION,
@@ -388,7 +388,7 @@ private void beginEvent(Event event) {
}
if (elementType.blockRestriction()) {
- for (SchemaType t = xsiType; !t.equals(elementType);
+ for (SchemaType t = xsiType; t != null && !t.equals(elementType);
t = t.getBaseType()) {
if (t.getDerivationType() == SchemaType.DT_RESTRICTION) {
emitFieldError(event, XmlErrorCodes.ELEM_LOCALLY_VALID$XSI_TYPE_BLOCK_RESTRICTION,
@@ -406,7 +406,7 @@ private void beginEvent(Event event) {
_localElement = sle;
if (sle.blockExtension() || sle.blockRestriction()) {
- for (SchemaType t = xsiType; !t.equals(elementType);
+ for (SchemaType t = xsiType; t != null && !t.equals(elementType);
t = t.getBaseType()) {
if ((t.getDerivationType() == SchemaType.DT_RESTRICTION && sle.blockRestriction()) ||
(t.getDerivationType() == SchemaType.DT_EXTENSION && sle.blockExtension())) {
diff --git a/src/test/java/misc/checkin/XsiTypeBlockValidateTest.java b/src/test/java/misc/checkin/XsiTypeBlockValidateTest.java
new file mode 100644
index 000000000..53821f74a
--- /dev/null
+++ b/src/test/java/misc/checkin/XsiTypeBlockValidateTest.java
@@ -0,0 +1,97 @@
+/* Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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 misc.checkin;
+
+import org.apache.xmlbeans.SchemaTypeLoader;
+import org.apache.xmlbeans.XmlBeans;
+import org.apache.xmlbeans.XmlError;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class XsiTypeBlockValidateTest {
+
+ private static final String UNION_MEMBER_INSTANCE =
+ "5";
+
+ private static XmlObject parse(String xsd, String instance) throws Exception {
+ SchemaTypeLoader loader = XmlBeans.loadXsd(new XmlObject[]{SchemaDocument.Factory.parse(xsd)});
+ return loader.parse(instance, null, null);
+ }
+
+ @Test
+ void unionMemberSubstitutionUnderElementBlock() throws Exception {
+ // xs:int is validly derived from the union, and block only excludes extension
+ String xsd =
+ "" +
+ " " +
+ " " +
+ "";
+
+ XmlObject doc = parse(xsd, UNION_MEMBER_INSTANCE);
+ List errors = new ArrayList<>();
+ assertTrue(doc.validate(new XmlOptions().setErrorListener(errors)), errors.toString());
+ }
+
+ @Test
+ void unionMemberSubstitutionUnderTypeBlock() throws Exception {
+ String xsd =
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "";
+
+ XmlObject doc = parse(xsd, UNION_MEMBER_INSTANCE);
+ assertDoesNotThrow(() -> doc.validate(new XmlOptions().setErrorListener(new ArrayList<>())));
+ }
+
+ @Test
+ void blockedExtensionIsStillReported() throws Exception {
+ String xsd =
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "";
+
+ XmlObject doc = parse(xsd,
+ "");
+
+ List errors = new ArrayList<>();
+ assertFalse(doc.validate(new XmlOptions().setErrorListener(errors)));
+ assertEquals(1, errors.size(), errors.toString());
+ assertEquals("cvc-elt.4.3d", errors.get(0).getErrorCode());
+ }
+}