[英]How can I use factored-out .xsd files from a resource jar to specify a JAXB schema?
我正在将XML文件解组到JAXB生成的Java对象中。 我希望解组器根据流程中的模式验证文件。 模式的.xsd
文件位于依赖项.jar
文件中。 我将模式设置为:
ClassLoader classLoader = getClass().getClassLoader();
InputStream schemaStream = classLoader.getResourceAsStream(schemaFilePath);
StreamSource schemaSource = new StreamSource(schemaStream);
Schema schema = factory.newSchema(schemaSource);
unmarshaller.setSchema(schema);
除了一个问题,大多数情况下都有效。 该架构具有分解到其他.xsd
文件中的一些复杂类型。 解组器似乎无法找到分解后的.xsd
文件,因为当我尝试设置架构时,我得到了SAXException
:
Cannot resolve the name 'tns:FactoredOutType' to a(n) 'type definition' component.
注意:从eclipse运行时,当它从target
文件夹而不是从.jar
文件引用.xsd
文件时,此方法运行良好。
任何人都有任何想法,我如何才能使分解后的.xsd
文件适用于依赖项的.jar
文件中的架构?
编辑:
如果有用的信息,顶级.xsd
在model
文件夹中,它引用的类型在model/common
,因此我将顶级.xsd
引用为:
"model/TopLevel.xsd"
...在其中,它引用分解出的.xsd
为:
"common/FactoredOut.xsd"
我们有许多导入/包含其他XSD的XSD。 我们通过将它们全部显式传递给SchemaFactory
来工作,而不是依靠导入来工作并在类路径上找到它。 代码如下所示:
try (InputStream xsdStream0 = ClaimLoadService.class.getResourceAsStream("/a.xsd");
InputStream xsdStream1 = ClaimLoadService.class.getResourceAsStream("/b.xsd");
InputStream xsdStream2 = ClaimLoadService.class.getResourceAsStream("/c.xsd");
InputStream xsdStream3 = ClaimLoadService.class.getResourceAsStream("/d.xsd");
InputStream xsdStream4 = ClaimLoadService.class.getResourceAsStream("/e.xsd");) {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schema = sf.newSchema(new Source[] { new StreamSource(xsdStream0), new StreamSource(xsdStream1),
new StreamSource(xsdStream2), new StreamSource(xsdStream3), new StreamSource(xsdStream4) });
...
} catch (SAXException | IOException | JAXBException e) {
logger.log(Level.INFO, e.getMessage(), e);
}
为了使JAXB完全满意,我们有时必须做的另一件事是确保导入模式实际上引用了导入的类型。 我不记得确切的错误表明我们需要采取解决方法,但这也许就是您要解决的问题。 这很俗气,但是我们通过一种变通办法来做到这一点:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://blah" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:name="http://blahblah" targetNamespace="http://blah"
elementFormDefault="qualified">
<xs:import namespace="http://blahblah" />
...
<xs:element name="ReferencesToMakeTheseElementsVisibleToThisJaxbContext">
<xs:complexType>
<xs:sequence>
<xs:element name="Business" type="name:type" minOccurs="0" />
...
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
基本上,我们创建一个complexType只是为了显式引用某些导入的类型。 只有在没有直接引用类型的情况下,我们才需要这样做。
通常,与XML相关的API具有一种允许程序员指定辅助文件位置的方法,这称为资源解析 。 对于Schema,我认为您必须实现LSResourceResolver
并将其传递给SchemaFactory.setResourceResolver
然后再调用newSchema
。
我最终通过将对newSchema
调用从传递StreamSource
切换为传递URL
来解决了问题,该URL
保留了基本URI,因此仍可以找到包含的类型(如@PetruGardea在他的评论中所述)。 产生的代码如下所示:
URL schemaURL = objectType.getClassLoader().getResource(schemaPath);
if (schemaURL != null) {
Schema schema = factory.newSchema(schemaURL);
unmarshaller.setSchema(schema);
}
谢谢大家的帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.