Rokko_11
Rokko_11

Reputation: 937

Java: XSD 1.1 schema validation of XML with asserts

I want to test generated XML files against a XSD 1.1 file containing assertions and I would like to do that in Java.

My XML content is:

<?xml version="1.0" encoding="UTF-8"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="person.xsd">
  <Name>John Doe</Name>
  <Age>17</Age>
</Person>

The XSD content is as follows and it contains two assertions:

<?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"
           vc:minVersion="1.1">
  <xs:element name="Person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Name" type="xs:string"/>
        <xs:element name="Age" type="xs:integer"/>
      </xs:sequence>
      <xs:assert test="Age &gt;= 18"/>
      <xs:assert test="(string-length(Name) > 15)"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

I use:

implementation("org.opengis.cite.xerces:xercesImpl-xsd11:2.12-beta-r1667115")

as dependency in my build.gradle.kts file. And the following Java code works:

// That's the important String which instantiates a xsd 1.1 aware schema factory + validator
SchemaFactory sf = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
Schema s = sf.newSchema(new StreamSource(getClass().getResourceAsStream(xsdFilePath)));
Validator v = s.newValidator();
v.validate(new StreamSource(getClass().getResourceAsStream(xmlFilePath)));

Hooray, now I get a validation exception:

Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 10; cvc-assertion: Assertion evaluation ('Age >= 18') for element 'Person' on schema type '#AnonType_Person' did not succeed. 

Problem

When I fix that age to 18, then I don't get a validation error regarding the name (length > 15), but I get

Exception in thread "main" java.lang.NoClassDefFoundError: com/ibm/icu/text/UTF16
    at org.eclipse.wst.xml.xpath2.processor.internal.function.FnStringLength.string_length(FnStringLength.java:105)
    at org.eclipse.wst.xml.xpath2.processor.internal.function.FnStringLength.evaluate(FnStringLength.java:74)
    at org.eclipse.wst.xml.xpath2.processor.DefaultDynamicContext.evaluate_function(DefaultDynamicContext.java:194)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1611)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.FunctionCall.accept(FunctionCall.java:46)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:2139)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.FilterExpr.accept(FilterExpr.java:52)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1258)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathExpr.accept(XPathExpr.java:43)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.do_bin_args(DefaultEvaluator.java:803)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:614)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.CmpExpr.accept(CmpExpr.java:106)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.do_expr(DefaultEvaluator.java:315)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1573)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.ParExpr.accept(ParExpr.java:40)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:2139)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.FilterExpr.accept(FilterExpr.java:52)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1258)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathExpr.accept(XPathExpr.java:43)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1607)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.FunctionCall.accept(FunctionCall.java:46)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:2139)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.FilterExpr.accept(FilterExpr.java:52)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:1258)
    at org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathExpr.accept(XPathExpr.java:43)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.do_expr(DefaultEvaluator.java:315)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.visit(DefaultEvaluator.java:336)
    at org.eclipse.wst.xml.xpath2.processor.ast.XPath.accept(XPath.java:43)
    at org.eclipse.wst.xml.xpath2.processor.DefaultEvaluator.evaluate(DefaultEvaluator.java:290)
    at org.apache.xerces.impl.xs.AbstractPsychoPathXPath2Impl.evaluateXPathExpr(Unknown Source)
    at org.apache.xerces.impl.xs.XMLAssertPsychopathXPath2Impl.evaluateOneAssertion(Unknown Source)
    at org.apache.xerces.impl.xs.XMLAssertPsychopathXPath2Impl.evaluateAssertionsFromAComplexType(Unknown Source)
    at org.apache.xerces.impl.xs.XMLAssertPsychopathXPath2Impl.processAllAssertionsOnElement(Unknown Source)
    at org.apache.xerces.impl.xs.XMLAssertPsychopathXPath2Impl.endElement(Unknown Source)
    at org.apache.xerces.impl.xs.XSDAssertionValidator.handleEndElement(Unknown Source)
    at org.apache.xerces.impl.xs.XMLSchemaValidator.assertionValidatorEndElementDelegate(Unknown Source)
    at org.apache.xerces.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
    at org.apache.xerces.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.jaxp.validation.StreamValidatorHelper.validate(Unknown Source)
    at org.apache.xerces.jaxp.validation.ValidatorImpl.validate(Unknown Source)
    at java.xml/javax.xml.validation.Validator.validate(Validator.java:124)
    at org.example.HelloWorld.validateXMLSchemaXerxes(HelloWorld.java:50)
    at org.example.HelloWorld.main(HelloWorld.java:31)
Caused by: java.lang.ClassNotFoundException: com.ibm.icu.text.UTF16
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
    ... 48 more

Question:

  1. How to fix that problem?
  2. In 2024, is there still no other open source library available which can validate XSD 1.1 assertions?

Upvotes: 0

Views: 39

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

  1. It's clearly failing because it's expecting ICU4J to be on the classpath, and it can't find it.

  2. No, there is no other open source implementation available. (It took me about a year to write the (commercial) schema processor in Saxon-EE, so this isn't exactly surprising.)

Upvotes: 0

Related Questions