摘要:将XML文档与JAVA对象互转是很常见的需求,如果XML定义很规整这很好实现。然而在现实中“不规矩”的XML可能更常见,Marshaller便无能为力了吗?下面是一个小技巧,调整一下思维便能重用Marshaller了,征服它们使工作更简单。
关键词:Marshaller, JAVA, XML

 
将一个类生成一个Json字符串、将一个Json字符串翻译成一个类(JAVA、C#代码),这一过程已经在“”博客中描述了;在实际项目应用中,如何将一个类生成一个XML文档或XML字符串,如何将一个XML文档翻译成一个类,这又是经常遇到的问题。比如,跟其它系统的交互中,其它系统定义的接口参数以XML格式定义,那么你写的系统就要解析并理解它传入的数据,或者把自己内部的数据转成按它规定的XML格式文档传出。在JAVA里,这一过程还蛮简单,使用Marshaller便可以很轻松的解决。
 
然而,有一些“不守规矩”的XML格式可能被其它系统定义了,它们定义的XML格式恰恰不是Marshaller天生有能力生成与解析的,我们对这种“不规矩"的XML就无计可施了吗?其实Marshaller还是很好用的,后来你会发现Marshaller的极限便不复存在。下面,我以一个简单的例子来证明我的这一观点,对于“不规矩”的XML我也是有办法将其制服的。
 
一、XML帮助类
 
首先,你得有一个XML帮助类,它提供的是最基础的,使用Marshaller使XML和JAVA对象互转,这对于规矩的XML文档们,便能以一挡百了。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
 
/**
 * XML的帮助类
 * 
 * @author wanganqi
 * @version v1.0
 * @since 2014年8月13日下午2:38:52
 */
public class XmlHelper
{
    /**
     * 将自定义数据对象转化为XML字符串
     * 
     * @param clazz 自定义数据类型
     * @param object 自定义数据对象
     * @return XML字符串
     * @throws JAXBException 异常
     */
    public static String objectToXML(Class clazz, Object object)
        throws JAXBException
    {
        String xml = null;
        JAXBContext context = JAXBContext.newInstance(clazz);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        Writer w = new StringWriter();
        m.marshal(object, w);
        xml = w.toString();
        return xml;
    }
 
    /**
     * 将XML字符串转化为自定义数据对象
     * 
     * @param clazz 自定义数据类型
     * @param xml XML字符串
     * @return 自定义数据对象
     * @throws JAXBException 异常
     */
    public static Object xmlToObject(Class clazz, String xml)
        throws JAXBException
    {
        JAXBContext context = JAXBContext.newInstance(clazz);
        Unmarshaller um = context.createUnmarshaller();
        return um.unmarshal(new StringReader(xml));
    }

}

 
​这对于这样规矩的:XML,就要定义这样的:JAVA类,一一对应,什么事情都能解决。
 
XML(规矩的)文件格式样例 JAVA生成方法
<?xml version="1.0" encoding="UTF-8"?>
<ANQIFILE>
    <HEAD>
        <ANQINUM>2</ANQINUM>
        <DATETIME>YYYY-MM-DD HH:MM:SS</DATETIME>
        <APPROVALNUM>王安琪No1</APPROVALNUM>
    </HEAD>
    <BODY>
        <ANQI>00001</ANQI>
        <ANQI>00002</ANQI>
        <ANQI>00003</ANQI>
    </BODY>
</ANQIFILE>
ANQIHead head = new ANQIHead(1, "YYYY-MM-DD HH:MM:SS", "王安琪No1");
ANQIBody body = new ANQIBody("00001", "00002", "00003");
ANQIFile anqiFile = new ANQIFile(head, body);

String xml = XmlHelper.objectToXML(ANQIFile.class, anqiFile);

补充说明:
下面的构造函数都隐去了,使用 String... anqis类似的参数,使用时请不要疑惑。

@XmlRootElement(name = "ANQIFILE")
@XmlType(propOrder = { "head", "body" })
public class ANQIFile
{
    private ANQIHead head;
 
    private ANQIBody body;
 
    
 
    @XmlElement(name = "HEAD")
    public ANQIHead getHead()
    {
        return head;
    }
 
    public void setHead(ANQIHead head)
    {
        this.head = head;
    }
 
    @XmlElement(name = "BODY")
    public ANQIBody getBody()
    {
        return body;
    }
 
    public void setBody(ANQIBody body)
    {
        this.body = body;
    }

}

-------------------------------------------------------------------------------------
public class ANQIBody
{
 
    private List<String> anqi;
 
    
 
    @XmlElement(name = "ANQI")
    public List<String> getAnqi()
    {
        return anqi;
    }
 
    public void setAnqi(List<String> anqi)
    {
        this.anqi = anqi;
    }

}

@XmlType(propOrder = { "anqiNum", "dateTime", "appovalNum" })
public class ANQIHead
{
 
    private int anqiNum;
    private String dateTime;
    private String appovalNum;
 
    
 
    @XmlElement(name = "ANQINUM")
    public int getAnqiNum()
    {
        return clueNum;
    }
 
    public void setAnqiNum(int clueNum)
    {
        this.clueNum = clueNum;
    }
 
    @XmlElement(name = "DATETIME")
    public String getDateTime()
    {
        return dateTime;
    }
 
    public void setDateTime(String dateTime)
    {
        this.dateTime = dateTime;
    }
 
    @XmlElement(name = "APPROVALNUM")
    public String getAppovalNum()
    {
        return appovalNum;
    }
 
    public void setAppovalNum(String appovalNum)
    {
        this.appovalNum = appovalNum;
    }

}

补充说明:
这里的构造函数都隐去了,使用

String... anqis类似的参数,使用时请不要疑惑。

 
 
二、将 自定义数据对象 与 XML(不规矩的)字符串 互转
 
现在我们有一个需求,把我们系统的JAVA对象转成按其它系统规定的XML格式文档传出,其它系统给了我们一份XML格式文档,希望我们能正确构造它;我写的系统要解析并理解其它系统传入的XML数据,同样的其它系统给了我们一份XML格式文档,希望我们能顺利解释它。看看我们是怎么做的吧。
XML格式:
XML(不规矩的)文件格式样例 JAVA使用方法 及 JAVA类
<?xml version="1.0" encoding="UTF-8"?>
<ANGELFILE>    
    <ANGEL>
        <WANG ID="00001" COUNT="2">
            <ANQI>
                <ITEM1>VALUE</ITEM1>
                <ITEM2>VALUE</ITEM2>
                <ITEMN>VALUE</ITEMN>
            </ANQI>
            <ANQI>
                <ITEM1>VALUE</ITEM1>
                <ITEM2>VALUE</ITEM2>
                <ITEMN>VALUE</ITEMN>
            </ANQI>
        </WANG>
    </ANGEL>

</ANGELFILE>

可以使用与上面规矩的XML类似的JAVA定义、使用方法。
 
现在看看它有多不规矩(其实也不是很不规矩啦,只是在ANQI这个节点下面的子节点名字每个都不一样,但都是以ITEM开头的)。
要生成这样的XML,可以先用ObjectToXML()生成都是以 ITEM 命名的节点,再通过DOM读取并更新ITEM名称,后面加上1、2...
要解析这样的XML,可以先把此XML过滤一遍,把ITEM*样的节点名称更新为 ITEM,再用XMLToObject()生成对象。
 
三、遇到的问题及改进方法
 
1、在使用Marshaller的过程中,出现了一点问题:生成XML时,并不按照配置的@XmlType(propOrder = { "1", "2" })的顺序,而是恰好相反的,这个问题目前还没有解决,唯一在网上查到的相关信息是说JAVA版本为6以下的会有这个BUG,但是我的JAVA版本为1.7,也出现了这个问题,望有知道解决方法的同学告知一下,请不吝赐教

2、对于不规矩的XML格式,更好的办法是使用Marshaller所支持的自定义解析器,上面的不规矩XML完全可以映射到Map对象上面去。这种方法更能支持更不规则的XML定义。网上不知有无已经实现的代码,知道的同学,请不吝赐教

最近项目工作量很大,每天都能学习到很多东西,项目管理的、JAVA使用的、界面规范的......不胜枚举,毕竟是第一次自己负责的项目,经验和教训肯定的巨大的。

作为一个项目经理,对作品、对自己的团队都觉得立马有了深深的责任感,也有了很大的压力,感谢组织的信任与支持,感谢团队的鼎力协作,感谢相关部门的大力配合,感谢姚老师的无私帮助,也感谢老婆默默的支持。

ありがとうございます 

如何集中资源做成一个优秀的项目,如何担当得起自己的责任,如何与各类角色沟通,真是任重而道远。

不规矩的xml与JAVA对象互相转换的小技巧-使用Marshaller的更多相关文章

  1. 使用XStream是实现XML与Java对象的转换(6)--持久化

    九.持久化 在第八节的示例中,当我们操作一组对象时,我们可以指定Writer.OutputStream来写出序列化后的XML数据,我们还可以指定Reader.InputStream来读取序列化后的XM ...

  2. 使用XStream是实现XML与Java对象的转换(4)--转换器

    七.转换器(Converter) 我们程序中的POJO是千变万化的,而且需求也是千奇百怪的,所以XStream中的内置的转换器的功能不一定能够满足我们的要求,所以我们就需要自己构建转换器. 1,一个基 ...

  3. 使用XStream是实现XML与Java对象的转换(3)--注解

    六.使用注解(Annotation) 总是使用XStream对象的别名方法和注册转换器,会让人感到非常的乏味,又会产生很多重复性代码,于是我们可以使用注解的方式来配置要序列化的POJO对象. 1,最基 ...

  4. 使用XStream是实现XML与Java对象的转换(1)--简介及入门示例

    一.简单介绍 XStream是thoughtworks开发的开源框架,用于实现XML数据于Java对象.Json数据的转换.它不需要schema或其他的mapping文件就可以进行java对象和xml ...

  5. 使用XStream是实现XML与Java对象的转换(5)--Object Stream

    八,Object Stream 之前的例子我们都是直接输出Xml成为String类型或者从String中获得并解析Xml,现在我们要处理输入流和输出流! 1,输出流(ObjectOutputStrea ...

  6. 使用XStream是实现XML与Java对象的转换(2)--别名

    五.使用别名(Alias) 首先,有这样一段Java代码: import java.util.ArrayList; import java.util.List; import com.thoughtw ...

  7. XML 和 java对象相互转换

    XML 和 java对象相互转换 博客分类: XML 和 JSON   下面使用的是JDK自带的类,没有引用任何第三方jar包. Unmarshaller 类使客户端应用程序能够将 XML 数据转换为 ...

  8. XStream轻松转换xml和java对象

    首先引入所需的jar: xstream-1.4.9.xpp3_min-1.1.4c.dom4j-1.6.1, 或用maven管理jar包时在pom.xml中添加: <!-- https://mv ...

  9. Java&Xml教程(十一)JAXB实现XML与Java对象转换

    JAXB是Java Architecture for XML Binding的缩写,用于在Java类与XML之间建立映射,能够帮助开发者很方便的將XML和Java对象进行相互转换. 本文以一个简单的例 ...

随机推荐

  1. SVN命令行怎么用?--转百度知道

    http://zhidao.baidu.com/link?url=uPWXURahp5KzdXbgrGTb9-r-abGaNC-J7dkhFkMhf062OJ1jeCM5wpBCgDR7bDg8uFr ...

  2. 使用rem单位的问题——Google下字体很大

    rem的看法 rem单位确实好处蛮多的,它是相对于根节点,让我们整个网站单位可以统一.还可以让我们的字体更好的自适应网站的大小.但是,你用过了就知道,它会出现一个问题: 用Chrome浏览器打开你做的 ...

  3. css三栏布局方案整理

    日常开发中,经常会用到css三栏布局,现将工作中常用的css 三栏布局整理如下: 什么是三栏布局: 三栏布局,顾名思义就是两边固定,中间自适应. 一. float布局 <!DOCTYPE htm ...

  4. SQL中的函数以及实例

    AVG (平均) COUNT (计数) MAX (最大值) MIN (最小值) SUM (总合) 运用函数的语法是: selecte  "函数名"("列名") ...

  5. [javaEE] jsp入门

    Servlet写java代码很好,但是拼接html的时候,非常不方便 JSP可以在html中嵌套java代码,这样在展示的时候,就会比较方便 Tomcat帮我们把jsp的页面翻译成了Servlet去运 ...

  6. number_formate 货币金额或数量格式化

    $row['formated_goods_price']    = number_format($row['goods_price'], 2, '.', ''); number_format() 函数 ...

  7. GET和POST请求的区别如下

    POST和GET都是向服务器提交数据,并且都会从服务器获取数据. 区别: 1.传送方式:get通过地址栏传输,post通过报文传输. 2.传送长度:get参数有长度限制(受限于url长度),而post ...

  8. spring实现固定时间定时器

    此文章是基于 搭建Jquery+SpringMVC+Spring+Hibernate+MySQL平台 一. jar包介绍 1. spring-framework-4.3.4.RELEASE 的 lib ...

  9. 微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆

    原创声明:本文为本人原创作品,绝非他处转账,转载请联系博主 从接触公众号到现在,开发维护了2个公众号,开发过程中遇到很多问题,现在把部分模块功能在这备案一下,做个总结也希望能给其他人帮助 工欲善其事, ...

  10. CSS3之盒模型

    1. 什么是盒模型? css中的每个元素都是一个盒模型, 包括html body元素, 浏览器解析css的时候也会把每个元素看成一个盒子来解析. 盒模型具备的属性(存在的特点)有: content ( ...