给定两个 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/