相关文章推荐
大力的眼镜  ·  Git: ...·  1 月前    · 
高大的小摩托  ·  Can not add ...·  1 年前    · 

Java解析XML的类库很多,本文记录用XStream库对XML的处理

背景
实际开发中,应用报文的格式一般都是JSON和XML;JSON大家都很熟悉(优秀类库:GSON/FastJson/Jackson),但对XML的解析可能并不熟悉,这主要是因为XML一般用于特定的领域:如金融和支付行业,想要和银联及网联对接,XML是少不了的

XStream的使用
XStream是解析XML的一款轻量级类库,简单快捷。下面以网联的交易查询接口为例,记录XML的序列化和反序列化的相关使用方法
在这里插入图片描述

报文结构如下:
在这里插入图片描述

  1. 创建对应的类(具体类信息添加在文末)
    在这里插入图片描述

  2. 创建XStream工具类

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class XmlUtil {
     * @param obj 要序列化的对象
     * @return 序列化后的xml字符串
    public static String toXml(Object obj) {
        XStream xStream = new XStream();
        xStream.autodetectAnnotations(true); // 自动发现注解
        try {
            return xStream.toXML(obj);
        } catch (Exception e) {
            throw new RuntimeException("Serialization object to xml error: " + e.getMessage());
     * @param is XML字符串的字节流
     * @param targetClazz xml反序列化的目标类
     * @param <T>
     * @return 目标类对象
    public static <T> T fromXml(InputStream is, Class<T> targetClazz) {
        XStream xStream = new XStream();
        // 设置安全模式
        XStream.setupDefaultSecurity(xStream);
        // 允许反序列化的类
        xStream.allowTypes(new Class[] {TransStatusInquiryResponse.class});
        xStream.processAnnotations(targetClazz); // 反序列化的类
        try {
            return (T) xStream.fromXML(is);
        } catch (Exception e) {
            throw new RuntimeException("Deserialization from xml to object error: " + e.getMessage());
  1. 测试序列化和反序列化的结果
public class Test {
    public static final String XML_NS = "name_space_string";
    public static final String ISO_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss";
    public static final String responseXml = "<root xmlns=\"name_space_string\">\n" +
            "  <MsgHeader>\n" +
            "    <MsgTp>epcc.302.001.01</MsgTp>\n" +
            "    <IssrId>ICBC00001</IssrId>\n" +
            "    <Drctn>21</Drctn>\n" +
            "    <SignSN>87654321</SignSN>\n" +
            "    <NcrptnSN></NcrptnSN>\n" +
            "    <DgtlEnvlp></DgtlEnvlp>\n" +
            "  </MsgHeader>\n" +
            "  <MsgBody>\n" +
            "    <SysRtnInf>\n" +
            "      <SysRtnCd>00000000</SysRtnCd>\n" +
            "      <SysRtnDesc></SysRtnDesc>\n" +
            "      <SysRtnTm>2020-11-29T15:41:15</SysRtnTm>\n" +
            "    </SysRtnInf>\n" +
            "    <BizInf>\n" +
            "      <RPFlg>foo</RPFlg>\n" +
            "      <OriSysRtnCd>foo</OriSysRtnCd>\n" +
            "      <OriSysRtnDesc>foo</OriSysRtnDesc>\n" +
            "      <OriBizstsCd></OriBizstsCd>\n" +
            "      <OriBizStsDesc></OriBizStsDesc>\n" +
            "      <OriTrxctgy>0115</OriTrxctgy>\n" +
            "      <OriTrxId>20201128888888888888888800022</OriTrxId>\n" +
            "      <OriTrxStatus>foo</OriTrxStatus>\n" +
            "      <DbtrBankId>foo</DbtrBankId>\n" +
            "      <CdtrBankId>foo</CdtrBankId>\n" +
            "      <OriTrxAmt>foo</OriTrxAmt>\n" +
            "      <OriBatchId>foo</OriBatchId>\n" +
            "      <OriSgnNo>foo</OriSgnNo>\n" +
            "      <PyerAcctTp>foo</PyerAcctTp>\n" +
            "      <PyerAcctId>foo</PyerAcctId>\n" +
            "      <PyerAcctNm>foo</PyerAcctNm>\n" +
            "      <AcctshrtId>foo</AcctshrtId>\n" +
            "      <ResfdAcctshrtId>foo</ResfdAcctshrtId>\n" +
            "    </BizInf>\n" +
            "  </MsgBody>\n" +
            "</root>";
    public static void main(String[] args) {
        String xmlStr = XmlUtil.toXml(buildRequestObj());
        System.out.println(xmlStr);
        System.out.println("--------------------------");
        TransStatusInquiryResponse inquiryResponse = XmlUtil.fromXml(new ByteArrayInputStream(responseXml.getBytes(StandardCharsets.UTF_8)), TransStatusInquiryResponse.class);
        System.out.println(inquiryResponse.toString());
    private static TransStatusInquiryRequest buildRequestObj() {
        TransStatusInquiryRequest inquiryRequest = new TransStatusInquiryRequest();
        inquiryRequest.setXmlns(XML_NS);
        MsgRequestHeader requestHeader = new MsgRequestHeader();
        requestHeader.setSndDt(DateTimeFormatter.ofPattern(ISO_DATE_TIME).format(LocalDateTime.now()));
        requestHeader.setMsgTp("epcc.301.001.01");
        requestHeader.setIssrId("ICBC00001");
        requestHeader.setDrctn("11");
        requestHeader.setSignSn("12345678");
        requestHeader.setNcrptnSn("");
        requestHeader.setDgtlEnvlp("");
        inquiryRequest.setMsgRequestHeader(requestHeader);
        MsgRequestBody requestBody = new MsgRequestBody();
        requestBody.setInstgId("12345678901234");
        requestBody.setRPFlg("2");
        OriginTrxInfo originTrxInfo = new OriginTrxInfo();
        originTrxInfo.setOriTrxCtgy("0115");
        originTrxInfo.setOriTrxId("20201128888888888888888800022");
        originTrxInfo.setOriTrxDtTm(DateTimeFormatter.ofPattern(ISO_DATE_TIME).format(LocalDateTime.now()));
        originTrxInfo.setOriAcctTp("00");
        originTrxInfo.setOrisgnNo("");
        requestBody.setOriginTrxInfo(originTrxInfo);
        inquiryRequest.setMsgRequestBody(requestBody);
        return inquiryRequest;

结果如下:

序列化,组装交易查询的请求报文:
<root xmlns="name_space_string">
  <MsgHeader>
    <SndDt>2020-11-29T15:46:55</SndDt>
    <MsgTp>epcc.301.001.01</MsgTp>
    <IssrId>ICBC00001</IssrId>
    <Drctn>11</Drctn>
    <SignSN>12345678</SignSN>
    <NcrptnSN></NcrptnSN>
    <DgtlEnvlp></DgtlEnvlp>
  </MsgHeader>
  <MsgBody>
    <InstgId>12345678901234</InstgId>
    <RPFlg>2</RPFlg>
    <OriTrxInf>
      <OriTrxCtgy>0115</OriTrxCtgy>
      <OriTrxId>20201128888888888888888800022</OriTrxId>
      <OriTrxDtTm>2020-11-29T15:46:55</OriTrxDtTm>
      <OriAcctTp>00</OriAcctTp>
      <OrisgnNo></OrisgnNo>
    </OriTrxInf>
  </MsgBody>
</root>
--------------------------
反序列化响应报文,结果如下:
TransStatusInquiryResponse(xmlns=name_space_string, msgResponseHeader=MsgResponseHeader(sndDt=null, msgTp=epcc.302.001.01, issrId=ICBC00001, drctn=21, signSn=87654321, ncrptnSn=, dgtlEnvlp=), msgResponseBody=MsgResponseBody(sysRtnInf=SysRtnInf(sysRtnCd=00000000, sysRtnDesc=, sysRtnTm=2020-11-29T15:41:15), bizInf=BizInf(rPFlg=foo, oriSysRtnCd=foo, oriSysRtnDesc=foo, oriBizstsCd=, oriBizStsDesc=, oriTrxctgy=0115, oriTrxId=20201128888888888888888800022, oriTrxStatus=foo, dbtrBankId=foo, cdtrBankId=foo, oriTrxAmt=foo, oriBatchId=foo, oriSgnNo=foo, pyerAcctTp=foo, pyerAcctId=foo, pyerAcctNm=foo, acctshrtId=foo, resfdAcctshrtId=foo)))

请求报文相关的类信息如下:

@Getter
@Setter
@ToString
@XStreamAlias("root") // 对应的XML中的标签名字
public class TransStatusInquiryRequest {
    @XStreamAlias("xmlns") // 对应的XML中的标签名字
    @XStreamAsAttribute // 声明root标签的属性
    private String xmlns;
    @XStreamAlias("MsgHeader") // 对应的XML中的标签名字
    private MsgRequestHeader msgRequestHeader;
    @XStreamAlias("MsgBody") // 对应的XML中的标签名字
    private MsgRequestBody msgRequestBody;
@Getter
@Setter
@ToString
@XStreamAlias("MsgHeader")
public class MsgRequestHeader {
    @XStreamAlias("SndDt")
    private String sndDt;
    @XStreamAlias("MsgTp")
    private String msgTp;
    @XStreamAlias("IssrId")
    private String issrId;
    @XStreamAlias("Drctn")
    private String drctn;
    @XStreamAlias("SignSN")
    private String signSn;
    @XStreamAlias("NcrptnSN")
    private String ncrptnSn;
    @XStreamAlias("DgtlEnvlp")
    private String dgtlEnvlp;
@Getter
@Setter
@ToString
@XStreamAlias("MsgBody")
public class MsgRequestBody {
    @XStreamAlias("InstgId")
    private String instgId;
    @XStreamAlias("RPFlg")
    private String rPFlg;
    @XStreamAlias("OriTrxInf")
    private OriginTrxInfo originTrxInfo;
@Getter
@Setter
@ToString
@XStreamAlias("OriTrxInf")
public class OriginTrxInfo {
    @XStreamAlias("OriTrxCtgy")
    private String oriTrxCtgy;
    @XStreamAlias("OriTrxId")
    private String oriTrxId;
    @XStreamAlias("OriTrxDtTm")
    private String oriTrxDtTm;
    @XStreamAlias("OriAcctTp")
    private String oriAcctTp;
    @XStreamAlias("OrisgnNo")
    private String orisgnNo;

响应报文对应的类信息如下:

@Getter
@Setter
@ToString
@XStreamAlias("root")
public class TransStatusInquiryResponse {
    // 对响应报文的校验可以使用Java Validation相关注解,非常方便
    @XStreamAlias("xmlns")
    @XStreamAsAttribute
    private String xmlns;
    @XStreamAlias("MsgHeader")
    private MsgResponseHeader msgResponseHeader;
    @XStreamAlias("MsgBody")
    private MsgResponseBody msgResponseBody;
@Getter
@Setter
@ToString
@XStreamAlias("MsgHeader")
public class MsgResponseHeader {
    @XStreamAlias("SndDt")
    private String sndDt;
    @XStreamAlias("MsgTp")
    private String msgTp;
    @XStreamAlias("IssrId")
    private String issrId;
    @XStreamAlias("Drctn")
    private String drctn;
    @XStreamAlias("SignSN")
    private String signSn;
    @XStreamAlias("NcrptnSN")
    private String ncrptnSn;
    @XStreamAlias("DgtlEnvlp")
    private String dgtlEnvlp;
@Getter
@Setter
@ToString
@XStreamAlias("MsgBody")
public class MsgResponseBody {
    @XStreamAlias("SysRtnInf")
    private SysRtnInf sysRtnInf;
    @XStreamAlias("BizInf")
    private BizInf bizInf;
@Getter
@Setter
@ToString
@XStreamAlias("SysRtnInf")
public class SysRtnInf {
    @XStreamAlias("SysRtnCd")
    private String sysRtnCd;
    @XStreamAlias("SysRtnDesc")
    private String sysRtnDesc;
    @XStreamAlias("SysRtnTm")
    private String sysRtnTm;
@Getter
@Setter
@ToString
@XStreamAlias("BizInf")
public class BizInf {
    @XStreamAlias("RPFlg")
    private String rPFlg;
    @XStreamAlias("OriSysRtnCd")
    private String oriSysRtnCd;
    @XStreamAlias("OriSysRtnDesc")
    private String oriSysRtnDesc;
    @XStreamAlias("OriBizstsCd")
    private String oriBizstsCd;
    @XStreamAlias("OriBizStsDesc")
    private String oriBizStsDesc;
    @XStreamAlias("OriTrxctgy")
    private String oriTrxctgy;
    @XStreamAlias("OriTrxId")
    private String oriTrxId;
    @XStreamAlias("OriTrxStatus")
    private String oriTrxStatus;
    @XStreamAlias("DbtrBankId")
    private String dbtrBankId;
    @XStreamAlias("CdtrBankId")
    private String cdtrBankId;
    @XStreamAlias("OriTrxAmt")
    private String oriTrxAmt;
    @XStreamAlias("OriBatchId")
    private String oriBatchId;
    @XStreamAlias("OriSgnNo")
    private String oriSgnNo;
    @XStreamAlias("PyerAcctTp")
    private String pyerAcctTp;
    @XStreamAlias("PyerAcctId")
    private String pyerAcctId;
    @XStreamAlias("PyerAcctNm")
    private String pyerAcctNm;
    @XStreamAlias("AcctshrtId")
    private String acctshrtId;
    @XStreamAlias("ResfdAcctshrtId")
    private String resfdAcctshrtId;
简单,流畅的API,但完全灵活
从java.io输入解析到org.w3c.dom.Document
 将org.w3c.dom.Document序列化为任何java.io输出
通过XSLT和自定义过滤器支持将java.io,SAX,StAX,JAXB输入转换为它们中的任何一个
通过XPath查询org.w3c.dom.Document以获取String,Boolean,Number,org.w3c.dom.Element或Node,并使用Java 8 Streaming API
				
常见的序列化方式 一、Protocol Buffer Protocol Buffers(也称protobuf)是Google公司设计的一种独立于开发语言,独立于平台的可扩展的结构化数据序列机制。通俗点来讲它跟xml和json是一类。是一种数据交互格式协议。 protocol buffer的使用还是相对简单点,唯一麻烦的就是多了一个预编译的过程,将.proto文件转换成.java文件。 jprotobuf jprotobuf是百度针对Java程序开发一套简易类库,目的是简化Protocol Buffer类库的使用。 二、fastJson fastjson 是由阿里巴巴开发的一个性能很好的Java 语言实现的 Json解析器和生成器。特点:速度快,测试表明fastjson具有极快的性能,超越任其他的java json parser。功能强大,完全支持java bean、集合、Map、日期、En
拳击手2java 此存储库包含与src/data/boxer目录中的xdrs.dtd文件对应的类层次结构。 它允许将带注释的 XML Boxer 输出快速反序列化Java 对象。 先决条件是 maven(用于解析)和构建和运行的(用于输出)。 修改属性文件并指定 CCG 解析器、Boxer 和模型的路径后,您可以从程序中调用 C&C 工具并自行处理输出(请参阅 )。
上周五看了GKCTF的babycat那题,接触了XMLDecoder的漏洞,看了几天还是没看太明白。。。太菜了呜呜。。所以这是第一篇,暂时分析到这里,前面的处理XML的流程没看明白,光写篇文章理一下后面的部分。等以后再来填坑了。 只是简单的记录自己的调试过程,非常失败,没搞太懂。 利用就是,写一个这样的xml: <object class="java.lang.ProcessBuilder"> <array class="jav
Java中的XML序列化是将Java对象转换为XML格式的过程。XML序列化可以用于数据持久化、数据传输等场景。Java提供了多种方式来实现XML序列化,包括JAXB、XStream、Dom4j等。 JAXB是Java Architecture for XML Binding的缩写,是Java SE 6及以上版本中自带的一种XML数据绑定技术。JAXB通过注解或XML配置文件来描述Java类与XML之间的映射关系,从而实现Java对象XML序列化反序列化。以下是一个使用JAXB进行XML序列化的示例代码: ```java // 定义一个Java类 @XmlRootElement public class Person { private String name; private int age; private String address; public String getName() { return name; public void setName(String name) { this.name = name; public int getAge() { return age; public void setAge(int age) { this.age = age; public String getAddress() { return address; public void setAddress(String address) { this.address = address; // 序列化Java对象XML public static void serializeToXml(Person person, String xmlFilePath) throws JAXBException { JAXBContext context = JAXBContext.newInstance(Person.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(person, new File(xmlFilePath)); // 反序列化XMLJava对象 public static Person deserializeFromXml(String xmlFilePath) throws JAXBException { JAXBContext context = JAXBContext.newInstance(Person.class); Unmarshaller unmarshaller = context.createUnmarshaller(); return (Person) unmarshaller.unmarshal(new File(xmlFilePath)); 使用JAXB进行XML序列化需要注意以下几点: 1. Java类需要使用@XmlRootElement注解标注为根元素。 2. Java类的属性需要使用@XmlAttribute或@XmlElement注解标注为XML属性或元素。 3. 序列化时需要创建JAXBContext和Marshaller,反序列化时需要创建JAXBContext和Unmarshaller。 4. 序列化时可以设置Marshaller的属性,如是否格式化输出。 除了JAXB外,XStream和Dom4j也是常用的XML序列化工具。XStream是一款简单易用的XML序列化框架,通过注解或代码配置来完成Java类与XML之间的映射关系。Dom4j是一款基于JavaXML解析器和生成器,可以快速方便地操作XML文档。无论使用哪种工具,XML序列化都是Java开发中常用的技术之一。