Java XSD 验证取决于提供 XSD 的顺序

标签 java xml validation xsd

给定两个 XSD 架构文件:

a.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="b.xsd"/>
    <xs:element name="TestMessage">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="TestSubItem"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

b.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="TestSubItem">
        <xs:complexType>
            <xs:attribute name="name" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="test"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
    </xs:element>
</xs:schema>

以下 java 代码成功验证了架构:

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.io.FileUtils;
import org.xml.sax.SAXException;

try
{
    String xsdDirectory = "C:\\XSDFiles";
    String xmlString = "<TestMessage xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <TestSubItem name=\"test\"/> </TestMessage>";

     Collection<File> xsdFiles = FileUtils.listFiles(new File(xsdDirectory), new String[] { "xsd", "XSD" }, false);
    List<Source> sourceList = new ArrayList<>();
    for (File xsdFile: xsdFiles) {
        sourceList.add(new StreamSource(xsdFile));
    }
    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

    // 0 then 1, so add a.xsd then b.xsd (alphabetical)
    Schema schema = factory.newSchema(new Source[] {sourceList.get(0), sourceList.get(1)});
    Validator validator = schema.newValidator();
    validator.validate(new StreamSource(new StringReader(xmlString)));
    System.out.println("valid");
}
catch (SAXException e)
{
    System.out.println(e.toString());
}

但是,如果您交换模式添加到源数组的顺序,则 XSD 将以相反的顺序添加(b 在 a 之前):

Schema schema = factory.newSchema(new Source[] {sourceList.get(1), sourceList.get(0)});

然后你会得到以下异常:

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 68; cvc-elt.1.a: Cannot find the declaration of element 'TestMessage'.

这在这里很好,因为它是一个任意的示例 - 但如果我从目录加载文件并且不知道“正确的排序顺序”,那么我如何获取代码来查找根元素跨越所有文件而不仅仅是找到的第一个文件?

最佳答案

newSchema(Source[] schemas) 的 Javadoc :

parsers may choose to ignore all but the first <import> for a given namespace

阅读 javadoc 中的完整描述以获取更多上下文信息。

因此仅使用列出的第一个文件。

a.xsd有一个 <xs:include>对于 b.xsd ,当 a.xsd 时它们都会被加载。是第一。

如果b.xsd是第一个,然后只有 b.xsd已加载,这意味着 <xs:element name="TestMessage">丢失,因此出现错误。

关于Java XSD 验证取决于提供 XSD 的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61225671/

相关文章:

java - Spring-Boot:使用 Redis 作为 Session Store 时出现异常

java - Xml解析包括内联解析

validation - 如何使用 RDF 模式验证 RDF

javascript - MVC5 - 检查用于搜索日期字段的 2 个日期(文本框)之间的重叠

java - unix - x windows/X11 问题

java - 类包不包含 src.main.java,但它存在并且 eclipse 提示它

java - 困惑如何在另一个类中键入比较器

xml - Scala/Lift 中是否(或是否)有 XML 和 JSON 可序列化对象的标准特征?

android - 在android中以编程方式更改可绘制颜色

c# - 带有 DateTime 参数的 .NET 标准程序集属性