zoukankan      html  css  js  c++  java
  • JAXB 中的@XmlElementWrapper注解生成问题

    JAXB 中的@XmlElementWrapper注解生成问题

    本文同步发表在 http://www.simonme.org/?p=220

    1. 面临的问题场景

    <?xml version="1.0" encoding="UTF-8"?>
    <root xmlns="http://www.example.org/JaxbEleWrapperSchema">
        <students>
            <student sno="001" name="Simon" />
            <student sno="002" name="Eva" />
        </students>
    </root>

    当我们需要用JAXB处理(生成或读取)这样的xml文件时,根据xjc默认生成的代码,会需要这样去使用

     

        @Test
        public void test()
        {
            Root root = new Root();
            Student stu = new Student();
            stu.setName("Simon");
            stu.setSno("001");
            Student stu1 = new Student();
            stu1.setName("Eva");
            stu1.setSno("002");
            
            Students students = new Students();
            students.getStudent().add(stu);
            students.getStudent().add(stu1);
            root.setStudents(students);
    
            String testFilename = "d:/test.xml";
            JAXBUtils.object2xmlFile(root, testFilename);
        }
    

    这样代码看起来貌似不太理想,主要是针对Students 对象处理的地方,貌似有点多余,其实本意上就是想用<students>这个标签把<student>元素包起来,无其他用处。怎样解决这个貌似多余代码的问题呢? JAXB提供了@XmlElementWrapper注解来做这个事情。

     

    2. 用@XmlElementWrapper注解使代码更精致

    将Root类的代码改造成这样:

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Root")
    public class Root {
    
        @XmlElementWrapper(name="students")
        @XmlElement(required = true)
        protected List<Student> student;
    
        public List<Student> getStudent()
        {
            if(student == null)
            {
                student = new ArrayList<Student>();
            }
            return student;
        }
    
        public void setStudent(List<Student> student)
        {
            this.student = student;
        }
    
    }

    这样测试代码只需要写成

     @Test
        public void test()
        {
            Root root = new Root();
            Student stu = new Student();
            stu.setName("Simon");
            stu.setSno("001");
            Student stu1 = new Student();
            stu1.setName("Eva");
            stu1.setSno("002");
            
            root.getStudent().add(stu);
            root.getStudent().add(stu1);
            
            String testFilename = "d:/test.xml";
            JAXBUtils.object2xmlFile(root, testFilename);
        }
        

     

    这样更精致,但是又一个问题来了,一般我们用JAXB,代码都是用xjc命令行或者xjc的ant task生成,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="test" default="run" basedir=".">  
    
        <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
            <classpath>
                <fileset dir="D:/004.work/02.tools/jaxb-ri-2.2.6/jaxb-ri-2.2.6/lib" includes="*.jar" />
            </classpath>
        </taskdef>
        
        <target name="run">
            <xjc destdir="D:/004.work/03.workspace/02.plugin_dev_demo/JaxbElementWarp/src" package="com.xxx.xxx.demo.xsd.test" >
                <schema dir="D:/004.work/03.workspace/02.plugin_dev_demo/JaxbElementWarp/src" includes="JaxbEleWrapper.xsd" />
            </xjc>
        </target>
        
    </project>

    但是这个我们手工干预的貌似很麻烦,如何让他自动生成@XmlElementWrapper这个注解,并对代码做相应调整。

     

    3. 如何用xjc生成@XmlElementWrapper注解

    需要使用github上的这个jaxb-xew-plugin.jarxjc插件(https://github.com/wumpz/jaxb-xew-plugin)。下面介绍如何使用。

    首先这个插件需要匹配JAXB 2.2版本,目前还不兼容于JAXB2.0版本,如果使用2.0版本,会出现NoSuchMethod之类的异常。去jaxb官网找到类似jaxb-ri-2.2.6 的zip包

    引用。

    编写ant脚本如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="test" default="run" basedir=".">  
    
        <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
            <classpath>
                <fileset dir="D:/004.work/02.tools/jaxb-ri-2.2.6/jaxb-ri-2.2.6/lib" includes="*.jar" />
                 <fileset dir="D:/004.work/02.tools" includes="jaxb-xew-plugin.jar" />
            </classpath>
        </taskdef>
        
        <target name="run">
            <xjc destdir="D:/004.work/03.workspace/02.plugin_dev_demo/JaxbElementWarp/src" package="com.xxx.xxx.demo.xsd.test" >
                <arg value="-Xxew" />
    <!--             <arg value="-Xxew:instantiate lazy" /> -->
                <schema dir="D:/004.work/03.workspace/02.plugin_dev_demo/JaxbElementWarp/src" includes="JaxbEleWrapper.xsd" />
            </xjc>
        </target>
        
    </project>

     

    具体用法可以参见https://github.com/wumpz/jaxb-xew-plugin文档。

    这个插件目前能做到我们想要的效果,但是多余的Students类仍然会生成,但是无碍功能,可以手动删除,并在ObjectFactory类中去掉对其的引用。

     

    4. jaxb-xew-plugin一点思考

    目前的玩法是先在xsd中定义上studetns这样的元素(把下面的student子元素包起来的元素),然后再用jaxb-xew-plugin插件生成。

    而不是:我们不在xsd文件中定义students元素,仅仅凭student元素是0到多个或者1到多个来生成@XmlElementWrapper注解。

  • 相关阅读:
    923c C. Perfect Security
    hdu ACM Steps Section 1 花式A+B 输入输出格式
    我回来了
    POJ–2104 K-th Number
    bzoj1009: [HNOI2008]GT考试
    bzoj1875: [SDOI2009]HH去散步
    1898: [Zjoi2005]Swamp 沼泽鳄鱼
    Hadoop
    程序员的自我修养
    Effective C++笔记
  • 原文地址:https://www.cnblogs.com/simoncook/p/2941357.html
Copyright © 2011-2022 走看看