Jaxb2Marshaller模式验证似乎不起作用

 _名花侑主 发布于 2023-02-08 10:01

我经历过Jaxb2Marshaller在进行解组时无法验证我对XSD的无效XML.我正在使用Spring 4.0.0.RELEASE和Java 7.

这是一个例子:

XSD文件:fruit.xsd




    

    
        
            
                
                    
                    
                
            
        
    

    
        
            
        
    

    
        
            
        
    


我使用Spring Tool Suite从这个XSD生成了JAXB POJO来com.testraptor.xml.jaxb打包.

我的XML文件无效:invalid.xml



    
    

如你所见,我打破了架构,因为在水果标签中有一个选择,我同时使用了香蕉和苹果.

我的Spring配置文件:app-config.xml




    


要测试的主要类:Main.java

package com.fruit.test;

import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.xml.sax.SAXException;

import com.fruit.xml.jaxb.Fruit;

public class Main {

    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                "app-context.xml");

        //--------------------------------SCHEMA VALIDATION IS OMITTED

        Jaxb2Marshaller jaxb2Unmarshaller = (Jaxb2Marshaller) appContext
                .getBean("marshaller");
        Resource schemaResource = appContext
                .getResource("classpath:fruit.xsd");
        jaxb2Unmarshaller.setSchema(schemaResource);

        Resource xml = appContext.getResource("classpath:invalid.xml");

        try {
            Fruit fruit = (Fruit) jaxb2Unmarshaller.unmarshal(new StreamSource(xml.getInputStream()));
            System.out.println("SCHEMA VALIDATION IS OMITTED:");
            System.out.println("Apple quantity is " + fruit.getApple().getQuantity());
            System.out.println("Banana quantity is " + fruit.getBanana().getQuantity());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //--------------------------------SCHEMA VALIDATION IS PASSED
        SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema;
        try {
            schema = sf.newSchema(schemaResource.getURL());
            JAXBContext context = JAXBContext.newInstance(Fruit.class);
            Unmarshaller unmarshaller = (Unmarshaller) context.createUnmarshaller(); 
            unmarshaller.setSchema(schema); 
            Fruit fruit2 = (Fruit) unmarshaller.unmarshal(xml.getInputStream());
            System.out.println("SCHEMA VALIDATION IS PASSED:");
            System.out.println("Apple quantity is " + fruit2.getApple().getQuantity());
            System.out.println("Banana quantity is " + fruit2.getBanana().getQuantity());
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JAXBException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }

}

当我运行代码时,我得到以下结果:

INFO: Loading XML bean definitions from class path resource [app-context.xml]
dec. 26, 2013 9:33:22 DE org.springframework.oxm.jaxb.Jaxb2Marshaller createJaxbContextFromContextPath
INFO: Creating JAXBContext with context path [com.fruit.xml.jaxb]
SCHEMA VALIDATION IS OMITTED:
Apple quantity is 3
Banana quantity is 5
javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 24; cvc-complex-type.2.4.d: Invalid content was found starting with element 'apple'. No child element is expected at this point.]
    at ...

正如您所看到的,当Unmarshaller可以验证时,Jaxb2Marshaller忘记验证我的无效XML文件.

任何人都可以告诉我我的代码可能有什么问题吗?

1 个回答
  • Jaxb2Marshaller在运行时配置时我遇到了同样的问题.通过Spring XML设置模式的建议解决方案让我想到:我的代码设置属性和Spring之间的区别是什么?

    答案很简单:Jaxb2Marshaller实现org.springframework.beans.factory.InitializingBean定义生命周期方法,afterPropertiesSet()并且BeanFactory在设置属性后由Springs调用此方法.

    所以解决方案就是调用afterPropertiesSet()after之后setSchema()用于设置schema属性.因为在该方法中,schema属性(它是一个org.springframework.core.io.Resource数组)实际上用于设置类型的内部模式字段,javax.xml.validation.Schema该字段稍后用于模式验证.

    例:

    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    Resource schema = new ClassPathResource("fruit.xsd");
    marshaller.setSchema(schema);
    marshaller.setContextPath("com.fruit.xml.jaxb");
    // manually call Spring lifecycle method which actually loads the schema resource
    marshaller.afterPropertiesSet();
    // use marshaller...
    

    2023-02-08 10:02 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有