Error validating XML with XSD version 1.1 with Xerces

128 views Asked by At

I am trying to validate an XML with XSD 1.1. I am not an expert in this, in fact it is the first time I try to create an XSD to validate an XML. It gives me the following error: s4s-elt-invalid-content.1: The content of '#AnonType_modelomodelos' is invalid. Element 'assert' is invalid, misplaced, or occurs too often.

I have downloaded the Xerces 1.1 version from here. https://dlcdn.apache.org//xerces/j/binaries/

I need to validate that in the available, blocked and canceled elements only one of them can have the value 'definitive'. The others may not have a positive value or numeric.

This is the XML.

<?xml version="1.1" encoding="UTF-8"?>
<modelos xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="sima-modelo.xsd">
    <modelo>
        <tipologia>DIAGNOSTICO</tipologia>
        <claseBase>Autodiag</claseBase>
        <disponible>3</disponible>
        <bloqueado></bloqueado>
        <cancelado>definitivo</cancelado>
        <borradoFisico>false</borradoFisico>
    </modelo>
    <modelo>
        <tipologia>POL</tipologia>
        <claseBase>Policy</claseBase>
        <disponible>30</disponible>
        <bloqueado>10</bloqueado>
        <cancelado>0</cancelado>
        <borradoFisico>true</borradoFisico>
    </modelo>
    <modelo>
        <tipologia>COLAB</tipologia>
        <claseBase>RRHH</claseBase>
        <disponible>1104</disponible>
        <bloqueado>0</bloqueado>
        <cancelado>0</cancelado>
        <borradoFisico>true</borradoFisico>
    </modelo>
</modelos>

Another version of XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           xmlns:xerces="http://xerces.apache.org"
           elementFormDefault="qualified"
           vc:minVersion="1.1">
           
    <xs:element name="modelos">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="modelo" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="tipologia" type="xs:string" />
                            <xs:element name="claseBase" type="xs:string" />
                            <xs:element name="disponible" type="Accion" />
                            <xs:element name="bloqueado" type="Accion" />
                            <xs:element name="cancelado" type="Accion" />
                            <xs:element name="borradoFisico" type="xs:boolean" />
                        </xs:sequence>
                    </xs:complexType>
                    <xs:assert test="count(disponible[.='definitivo']) + count(bloqueado[.='definitivo']) + count(cancelado[.='definitivo']) = 1" />
                    <xs:assert test="not(disponible = bloqueado or disponible = cancelado or bloqueado = cancelado)" />
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:simpleType name="Accion">
        <xs:union>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="" />
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType id="positiveInteger">
                <xs:restriction base="xs:nonNegativeInteger">
                    <xs:minInclusive value="0" />
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType>
                <xs:restriction base="xs:token">
                    <xs:enumeration value="definitivo" />
                </xs:restriction>
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>

</xs:schema>

XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           xmlns:xerces="http://xerces.apache.org"
           elementFormDefault="qualified"
           vc:minVersion="1.1">

    <xs:simpleType name="Accion">
        <xs:union>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value=""/>
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType id="positiveIntegerOrDefinitivo">
                <xs:restriction base="xs:string">
                    <xs:pattern value="\d+|definitivo"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>

    <xs:element name="modelos">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="modelo" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="tipologia" type="xs:string"/>
                            <xs:element name="claseBase" type="xs:string"/>
                            <xs:element name="disponible" type="Accion"/>
                            <xs:element name="bloqueado" type="Accion"/>
                            <xs:element name="cancelado" type="Accion"/>
                            <xs:element name="borradoFisico" type="xs:boolean"/>
                        </xs:sequence>
                        <xs:assert test="( count(disponible[.='definitivo']) + count(bloqueado[.='definitivo']) + count(cancelado[.='definitivo']) ) = 1"/>
                        <xs:assert test="not(disponible = bloqueado or disponible = cancelado or bloqueado = cancelado)"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

The last version of XSD with the same message.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
    xmlns:xerces="http://xerces.apache.org"
    elementFormDefault="qualified" vc:minVersion="1.1">

    <xs:element name="modelos" type="ModelosType"/>

    <xs:complexType name="ModelosType">
        <xs:sequence>
            <xs:element name="modelo" type="ModeloType" maxOccurs="unbounded" minOccurs="1"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="ModeloType">
        <xs:sequence>
            <xs:element name="tipologia" type="xs:string" />
            <xs:element name="claseBase" type="xs:string" />
            <xs:element name="disponible" type="Accion" />
            <xs:element name="bloqueado" type="Accion" />
            <xs:element name="cancelado" type="Accion" />
            <xs:element name="borradoFisico" type="xs:boolean" />
        </xs:sequence>
        <xs:assert test="count(disponible[.='definitivo']) + count(bloqueado[.='definitivo']) + count(cancelado[.='definitivo']) = 1" />
        <xs:assert test="not(disponible = bloqueado or disponible = cancelado or bloqueado = cancelado)" />
    </xs:complexType>
    
    <xs:simpleType name="Accion">
        <xs:union>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="" />
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType id="positiveInteger">
                <xs:restriction base="xs:nonNegativeInteger">
                    <xs:minInclusive value="0" />
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType>
                <xs:restriction base="xs:token">
                    <xs:enumeration value="definitivo" />
                </xs:restriction>
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>
</xs:schema>

I am using Eclipse 2022-12 and I think that the XML editor does not correctly validate the XSD assertion. s4s-elt-invalid-content.1: The content of '#AnonType_modelomodelos' is invalid. Element 'assert' is invalid, misplaced, or occurs too often. enter image description here

I have the downloaded libraries of the Xerces version 2.12.2 xml schema 1.1 configured in the classpath. These are the jars. They are right?.

ext-libs/resolver.jar
ext-libs/serializer.jar
ext-libs/xml-apis.jar
ext-libs/xercesImpl.jar
ext-libs/org.eclipse.wst.xml.xpath2.processor_1.2.1.jar
ext-libs/cupv10k-runtime.jar
ext-libs/icu4j.jar

I have searched Maven for the libraries but apparently they do not support XSD 1.1

This is the result of the validation with the schema that you tell me you have modified:

org.xml.sax.SAXParseException: cvc-assertion: Assertion evaluation ('count(*[local-name()=('blocked','cancelled','available') and text()='final']) eq 1') for element 'modelo' on schema type '#AnonType_modelomodelos' did not succeed.

Validation method

static final String W3C_XML_SCHEMA_11_NS_URI = "http://www.w3.org/XML/XMLSchema/v1.1";

    public static boolean validateXMLSchema(String xsdPath, String xmlPath) {

        try {
            SchemaFactory factory = SchemaFactory.newInstance(W3C_XML_SCHEMA_11_NS_URI);
            Schema schema = factory.newSchema(new File(xsdPath));
            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(xmlPath)));
        } catch (IOException | SAXException e) {
            LOGGER.error("Error validando 'modelos.xml' {}: ", xmlPath, e);
            return false;
        }
        return true;
    }

The complete rules are:

We have a list of models, each model with the following properties:

  • typology: allows a string, is required.
  • BaseClass: allows a string, is required.
  • disponible: allows positive numbers or the string 'definitivo'.
  • bloqueado: allows positive numbers or the string 'definitivo'.
  • cancelado: allows positive numbers or the string 'definitivo'.
  • borradoFisico: boolean.
  • The following rules are for the disponible, bloqueado and cancelado properties: Only one of them can have the value 'definitivo'.
  • They can have a value of 0, any positive numeric value or empty.
  • If disponible is equal definitivo and bloqueado + cancelado != 0, then custom error.
  • If bloqueado is equal to definitivo and cancelado is != 0, then custom error.
2

There are 2 answers

3
Yitzhak Khabinsky On

Please try the following XSD.

As @MartinHonnen already mentioned, the asserts were in the wrong location.

  • I modified the 1st assert.
  • Please clarify business rule(s) for the 2nd assert.

You can get the original Xerces2 Java 2.12.2 (XML Schema 1.1) here: The Apache Xerces™ Project - Downloads

I am using Oxygen XML Developer v.26.0. It is an XML IDE.

So, the XSD below is legit. It is tested, and working perfectly fine in Oxygen. Your XML sample is invalid because of the 2nd assert.

As @MartinHonnen already pointed out, the 2nd assert is using XML elements that belong to Accion user defined data type. It is using a union of different built-in data types: "xs:string", "xs:nonNegativeInteger", "xs:token". That's why the 2nd assert is constantly failing the validation.

When I commented out the 2nd assert, your XML became valid against the XSD.

XSD 1.1

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           xmlns:xerces="http://xerces.apache.org"
           elementFormDefault="qualified" vc:minVersion="1.1">
    <xs:element name="modelos">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="modelo" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="tipologia" type="xs:string"/>
                            <xs:element name="claseBase" type="xs:string"/>
                            <xs:element name="disponible" type="Accion"/>
                            <xs:element name="bloqueado" type="Accion"/>
                            <xs:element name="cancelado" type="Accion"/>
                            <xs:element name="borradoFisico" type="xs:boolean"/>
                        </xs:sequence>
                        <xs:assert test="count(*[local-name()=('bloqueado','cancelado','disponible') and text()='definitivo']) le 1"/>
                        <xs:assert test="not(disponible = bloqueado or disponible = cancelado or bloqueado = cancelado)"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:simpleType name="Accion">
        <xs:union>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value=""/>
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType id="positiveInteger">
                <xs:restriction base="xs:nonNegativeInteger">
                    <xs:minInclusive value="0"/>
                </xs:restriction>
            </xs:simpleType>
            <xs:simpleType>
                <xs:restriction base="xs:token">
                    <xs:enumeration value="definitivo"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>
</xs:schema>
0
Marco Osorio On

this is my solution. Thanks to all!

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
    xmlns:xerces="http://xerces.apache.org" elementFormDefault="qualified"
    vc:minVersion="1.1"
>
    <xs:element name="modelos" type="ModelosType" />
    
    <xs:complexType name="ModelosType">
        <xs:sequence>
            <xs:element name="modelo" type="ModeloType"
                maxOccurs="unbounded" minOccurs="1" />
        </xs:sequence>
    </xs:complexType>
    
    <xs:complexType name="ModeloType">
        <xs:sequence>
            <xs:element name="tipologia" type="xs:string" />
            <xs:element name="claseBase" type="xs:string" />
            <xs:element name="disponible" type="Action" />
            <xs:element name="bloqueado" type="Action" />
            <xs:element name="cancelado" type="Action" />
            <xs:element name="borradoFisico" type="xs:boolean" />
        </xs:sequence>
        <xs:assert
            test="(count(*[local-name()=('bloqueado','cancelado','disponible') and text()='definitivo']) eq 1 or
                   count(*[local-name()=('bloqueado','cancelado','disponible') and text()='definitivo']) eq 0 ) "
            xerces:message="Entre los elementos 'disponible', 'cancelado' y 'bloqueado', sólo uno de ellos puede tener el valor 'definitivo'. Revise el modelo"/>

        <!-- Validación: disponible = 'definitivo' entonces bloqueado y cancelado = 0 -->
        <xs:assert test="if (disponible='definitivo') then ((bloqueado='0' or bloqueado='') and (cancelado='0' or cancelado='') ) else true()"
                    xerces:message="Revise el modelo. Si disponible = 'definitivo' entonces bloqueado y cancelado = 0 o vacío"/>
                  
        <xs:assert test="if (bloqueado='definitivo') then (cancelado='0' or cancelado='') else true()"
                    xerces:message="Revise el modelo. Si bloqueado = 'definitivo' entonces cancelado = 0 o vacío"/>
                    
    </xs:complexType>
    
    <xs:simpleType name="Action">
        <xs:restriction base="xs:string">
            <xs:pattern value="|0|[1-9][0-9]*|definitivo" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>