简体   繁体   English

JAXB如何针对更多模式验证xml

[英]JAXB How to validate xml against more schemas

I am using the following code: 我正在使用以下代码:

    Unmarshaller unmarshaller = inputXmlContext.createUnmarshaller();
    SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
    URL urlSchema = ProbeOutputTranslator.class.getResource("/a.xsd");
    Schema schema = sf.newSchema(new File(urlSchema.toURI()));

To validate an xml against a.xsd . 针对a.xsd验证xml。 The problem is that a.xsd defines an abstract element and the containing element for it: 问题是a.xsd定义了一个抽象元素及其包含元素:

<xs:complexType name="abstract_operation" abstract="true"/>

<xs:element name="operation" type="ac:abstract_operation"/>

<xs:complexType name="so_operations">
    <xs:sequence>
        <xs:element ref="ac:operation" minOccurs = "0" maxOccurs="unbounded"/> 
    </xs:sequence>
</xs:complexType>

The concrete types are defined in b.xsd . 具体类型在b.xsd中定义。 In the xml file, the default namespace is a.xsd , b.xsd 's namespace is bound to prefix ops and it looks like this: 在xml文件中,默认名称空间是a.xsdb.xsd的名称空间绑定到ops前缀,如下所示:

<so_operations>
    <ops:a_concrete_operation>
                 ....
    </ops:a_concrete_operation>
</so_operations>

This setup of course causes validation error when the above mentioned code is used. 当使用上述代码时,此设置当然会导致验证错误。 How do I achieve that also b.xsd schema is taken in consideration when being validated? 如何在验证时也考虑到b.xsd模式?

The schemas are located only in program's resources (therefore schema location cannot be defined in xml file). 模式仅位于程序的资源中(因此,模式位置不能在xml文件中定义)。

You can combine the multiple schemas into a single schema programmatically and then validate against the combined schema. 您可以通过编程将多个架构组合为一个架构,然后针对组合的架构进行验证。

SchemaFactory.newSchema() has a variant that takes an array of source documents, and combines them into a single Schema instance. SchemaFactory.newSchema()具有一个变体,该变体采用一组源文档,并将它们组合为一个Schema实例。 However, this method is documented to behave as if creating a new schema document with import directives for each of the source documents. 但是,已记录此方法的行为,就像为每个源文档创建一个具有导入指令的新架构文档一样。 As a result, you can't combine source files with the same target namespace, and you must order the source documents so that definitions in one namespace are available when requested from another (I haven't found anything in the docs to justify this). 结果,您无法将源文件与相同的目标名称空间合并,并且必须对源文档进行排序,以便在另一个名称空间请求时可以使用一个名称空间中的定义(我在文档中没有找到任何证明这一点的理由) 。

Provided that your schema documents are accessible via URL or filesystem, the best solution is to create a single top-level schema document, and use explicit import and include directives to reference your definitions. 如果您可以通过URL或文件系统访问架构文档,则最佳解决方案是创建一个顶级架构文档,并使用显式import和include指令引用您的定义。

Below code may help in getting starting: 以下代码可能有助于入门:

URL xsdUrlA = this.getClass().getResource("a.xsd");
URL xsdUrlB = this.getClass().getResource("b.xsd");

SchemaFactory schemaFactory = schemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//---
String W3C_XSD_TOP_ELEMENT =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n"
+ "<xs:include schemaLocation=\"" +xsdUrlB.getPath() +"\"/>\n"
+ "<xs:include schemaLocation=\"" +xsdUrlA.getPath() +"\"/>\n"
+"</xs:schema>";
Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(W3C_XSD_TOP_ELEMENT), "xsdTop"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM