使用 JAXB 对 Schema 进行验证

Posted

技术标签:

【中文标题】使用 JAXB 对 Schema 进行验证【英文标题】:Validating against a Schema with JAXB 【发布时间】:2011-01-30 07:34:49 【问题描述】:

我一直在寻找解决这个问题的时间太长了考虑如何方便听起来是那么我来一些帮助。 P>

我有我与XJC用于创建我的JAXB绑定的XML架构。当形成良好的XML这工作得很好。不幸的是,还时不能很好地形成的XML不抱怨。我无法弄清楚如何做正确的全面验证在架构上,当我试图来解读一个XML文件。 P>

我已经成功地使用ValidationEventCollector来处理事件,这适用于XML解析错误,如不匹配的标签,但不会引发任何事件时有所需标签,但是完全不存在。 P>

这是我所看到的验证可以做到againsta模式,但你必须知道的路径,模式,以将其传递到的setSchema()方法。我的问题是,路径架构存储在XML头,我不能在这里的模式将是运行时间knwo。这就是为什么它存储在XML文件中: P>

<?xml version="1.0" encoding="utf-8"?>
<DDSSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/a/big/long/path/to/a/schema/file/DDSSettings.xsd">
<Field1>1</Field1>
<Field2>-1</Field2>

...等

每个例子中我看到的setValidating用途(真),这是现在已经过时,所以抛出异常。 P>

这是Java代码,我到目前为止,这似乎只能做XML验证,而不是架构验证: P>

try 
    JAXBContext jc = new JAXBContext() 
        private final JAXBContext jaxbContext = JAXBContext.newInstance("blah");

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException 
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            ValidationEventCollector vec = new ValidationEventCollector() 
                @Override
                public boolean handleEvent(ValidationEvent event) throws RuntimeException 
                    ValidationEventLocator vel = event.getLocator();
                    if (event.getSeverity() == event.ERROR || event.getSeverity() == event.FATAL_ERROR) 
                        String error = "XML Validation Exception:  " + event.getMessage() + " at row: " + vel.getLineNumber() + " column: " + vel.getColumnNumber();
                        System.out.println(error);
                    
                    m_unmarshallingOk = false;
                    return false;
                
            ;
            unmarshaller.setEventHandler(vec);

            return unmarshaller;
        

        @Override
        public Marshaller createMarshaller() throws JAXBException 
            throw new UnsupportedOperationException("Not supported yet.");
        

        @Override
        @SuppressWarnings("deprecation")
        public Validator createValidator() throws JAXBException 
            throw new UnsupportedOperationException("Not supported yet.");
        
    ;

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));
 catch (UnmarshalException ex) 
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
    Level.SEVERE,
    null, ex);
 catch (JAXBException ex) 
    Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
    Level.SEVERE,
    null, ex);

那么,什么是做到这一点的验证的正确方法?我期待有要对JAXB生成的类一个validate()方法,但我想这将是对Java太简单。 P>

【问题讨论】:

【参考方案1】:

好的,我找到了解决方案。使用架构工厂创建架构,但不指定架构文件,使其与 XML 文件中指定的 noNamespaceSchemaLocation 一起工作。

所以上面的代码已经添加了这个:

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(schema);
m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));

耻辱花了 24 小时才找到答案!

SchemaFactory.newSchema() 的 javadoc 说:

对于 XML Schema,此方法创建一个 执行验证的模式对象 通过使用指定的位置提示 文件。

返回的 Schema 对象假定 如果文件提到相同 架构位置提示中的 URL,它们 将始终解析为相同的架构 文档。这个假设允许 重用已解析的实现 模式文档的结果,以便 针对相同的多个验证 架构将运行得更快。

【讨论】:

有趣,我不知道。我冒昧地在您的答案中添加了一些信息,以供将来参考。 根据 javadocs,不要显式指定 XMLSchema URL,而是使用此处指定的 XMLConstants 中的适当值:docs.oracle.com/javase/6/docs/api/index.html?javax/xml/… @icfantv 我们是对的,我使用:Schema schema = SchemaFactory.newInstance (XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema (); // 但参考是:docs.oracle.com/javase/6/docs/api/index.html?javax/xml/… - 另外我不理解这个解决方案的事情是 url 是恒定的:它不引用我们自己的架构的位置(对我来说并不明显) oops:直接引用 XMLConstants:docs.oracle.com/javase/6/docs/api/javax/xml/…【参考方案2】:

据我所知,您只需将带有Marshaller.setSchema() 的架构设置为由SchemaFactory 从您的DDSSettings.xsd 创建的架构。这将打开验证。

【讨论】:

但问题是我在编译时不知道该 XSD 文件的路径,并且在运行时没有给出它 - 它仅存储在 XML 文件标题中。 但是如果你有 jaxb 类,它们应该是从模式中生成的。为什么不在您的项目中包含架构? JAXB 没有必须使用模式和生成的代码,它在没有模式的情况下也能很好地工作。

以上是关于使用 JAXB 对 Schema 进行验证的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JAXB2.0 禁用 DTD 获取

JAXB - XML Schema Types, Defining Subtypes

JAXB - XML Schema Types, Binary Data

JAXB - XML Schema Types, Date and Time

使用带有签名、加密和编码的 JAXB

XML编程总结——使用JAXB进行java对象和xml格式之间的相互转换