XML文件解析处理

最近在做一个银企直连的项目,因为接受到的数据为XML格式的String。且几乎每一次接收到的XML文件格式以及内容基本都不一样。所以目前在dom4j的基础上,加上对反射的应用,直接把XML数据转为(固定格式,内部变量可多不可少的)实体类。这样方便了对XML数据的选择应用以及对XML数据的后续处理。

准备环境

1.引入相关Maven依赖

	<!-- dom4j处理XML数据 -->
	<dependency>
	  <groupId>dom4j</groupId>
	  <artifactId>dom4j</artifactId>
	  <version>1.6</version>
	</dependency>
	<!-- 引入lombak插件 -->
	<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
	</dependency>

2.准备好需要解析的字符串(方便测试)

String xmlString= 
				"<?xml version=\"1.0\" encoding=\"GB2312\"?>" +
                "<CMBC trnCode=\"Xfer\" security=\"none\" lang=\"chs\" header=\"100\" version=\"100\" >" +
	                "<responseHeader>" +
		                "<status>" +
			                "<code>0</code>" +
			                "<severity>info</severity>" +
			                "<message>ok</message>" +
		                "</status>" +
	                "<dtServer>2020-08-24 09:38:32</dtServer>" +
	                "<userKey>N</userKey>" +
	                "<dtDead></dtDead>" +
	                "<language>chs</language>" +
	                "</responseHeader>" +
	                "<xDataBody>" +
		                "<transfer>" +
			                "<trnId>zhouyf</trnId>" +
			                "<svrId>31301202008246046584784313000000</svrId>" +
			                "<insId>00001</insId>" +
			                "<balance>59289497.37</balance>" +
		                "</transfer>" +
	                "</xDataBody>" +
                "</CMBC>";

ps: 不需要XML头数据,直接从CMBC标签开始解析。(为了方便看专门进行了缩进)可以看到这个XML标签有4级。如:CMBC->responseHeader->status->code.

直接开始解析XML

话不多说,直接代码

// 创建SAXReader的对象reader
SAXReader reader = new SAXReader();
try {
    // 通过reader对象的read方法加载books.xml文件,获取docuemnt对象。
    Document document = reader.read(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
    // 通过document对象获取根节点bookstore
    Element oneEle = document.getRootElement();
    List<Attribute> cmbcAttrs = oneEle.attributes();
    //组装根节点中的参数
    for (Attribute attr : cmbcAttrs) {
        System.out.println("[attr : "+oneEle.getName()+"]  "+attr.getName()+" : "+attr.getValue());
    }
    //剩余的不用组装attr参数 一共有四级
    //【第二级】
    Iterator twoDocument = oneEle.elementIterator();
    //twoDocument.hasNext()判断该标签是否拥有子标签,如果有就继续解析
    if(twoDocument.hasNext()) {
        while (twoDocument.hasNext()) {
            Element twoEle = (Element) twoDocument.next();
             //【第三级】
            Iterator threeDocument = twoEle.elementIterator();
            if (threeDocument.hasNext()) {
                while (threeDocument.hasNext()) {
                    Element threeEle = (Element) threeDocument.next();
                     //【第四级】
                    Iterator fourDocument = threeEle.elementIterator();
                    if (fourDocument.hasNext()) {
                        while (fourDocument.hasNext()) {
                            Element fourEle = (Element) fourDocument.next();
                            System.out.println("[ele : "+fourEle.getParent().getName()+"]  "+ fourEle.getName() + " :" + fourEle.getStringValue());
                        }
                    } else System.out.println("[ele : "+threeEle.getParent().getName()+"]  "+ threeEle.getName() + " :" + threeEle.getStringValue());
                }
            } else System.out.println("[ele : "+twoEle.getParent().getName()+"]  "+ twoEle.getName() + " :" + twoEle.getStringValue());
        }
    }else System.out.println("[ele : "+oneEle.getParent().getName()+"]  "+ oneEle.getName() + " :" + oneEle.getStringValue());
} catch (DocumentException e) {
    e.printStackTrace();
}

输出结果:

[attr : CMBC]  trnCode : Xfer
[attr : CMBC]  security : none
[attr : CMBC]  lang : chs
[attr : CMBC]  header : 100
[attr : CMBC]  version : 100
[ele : status]  code :0
[ele : status]  severity :info
[ele : status]  message :ok
[ele : responseHeader]  dtServer :2020-08-24 09:38:32
[ele : responseHeader]  userKey :N
[ele : responseHeader]  dtDead :
[ele : responseHeader]  language :chs
[ele : transfer]  trnId :zhouyf
[ele : transfer]  svrId :31301202008246046584784313000000
[ele : transfer]  insId :00001
[ele : transfer]  balance :59289497.37

可以看到XML文件中的内容已经全部被解析出来了,但是这还不是我想要的。因为目前最多可以把这些数据封装成map格式,但是对动态的去引用的时候还是很不方便。所以请往下看…

通过反射,把XMl解析到实体类中

1.建立对应的实体类(实体类中的变量可多不可少,我直接建的内部类。为了演示特意多建上个多余的字段)

@Data
public class CMBC {
    /**
     * 交易请求代码
     */
    private String trnCode;
    /**
     * 安全信息
     */
    private String security;
    /**
     * 语言
     */
    private String lang;
    /**
     * 请求头信息
     */
    private String header;
    /**
     * 版本信息
     */
    private String version;
    /**
     * 响应头
     */
    private ResponseHeader responseHeader;
    /**
     * 返回数据
     */
    private XDataBody xDataBody;
    /**
     * 多余的字段
     */
     private String moreString;
	/**
	 * 新建的时候初始化期内部类,不然后面通过反射来实例化对象的时候可能出现问题
	 */
    public CMBC(){
        this.responseHeader = this.new ResponseHeader();
        this.xDataBody = this.new XDataBody();
    }

    @Data
    public class ResponseHeader{

        private Status status;

        private String dtServer;

        private String userKey;

        private String dtDead;

        private String language;

		/**
         * 多余的字段
         */
        private String moreString;

        public ResponseHeader(){
            this.status = this.new Status();
        }

        /**
         * 交易状态码
         */
        @Data
        public class Status{
            private String code;
            private String severity;
            private String message;
			/**
	         * 多余的字段
	         */
	        private String moreString;
        }
    }


    @Data
    public class XDataBody{
        /**
         * 转账详情
         */
        private Transfer transfer;

        public XDataBody(){
            this.transfer = this.new Transfer();
        }

        @Data
        public class Transfer{
            /**
             * 客户端交易的唯一标志
             */
            private String trnId;
            /**
             * 服务器该笔交易的标识
             */
            private String svrId;
            /**
             * 指令 ID,请求时给出的 ID
             */
            private String insId;
            /**
             * 余额
             */
            private String balance;
        }
    }
}

2.在XML解析中添加对反射的引用,直接解析为实体对象

CMBC cmbc = new CMBC();
// 创建SAXReader的对象reader
SAXReader reader = new SAXReader();
try {
    // 通过reader对象的read方法加载books.xml文件,获取docuemnt对象。
    Document document = reader.read(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
    // 通过document对象获取根节点bookstore
    Element oneEle = document.getRootElement();
    List<Attribute> cmbcAttrs = oneEle.attributes();
    //组装CMBC根节点中的参数
    for (Attribute attr : cmbcAttrs) {
        String methodName = "set"+attr.getName().substring(0, 1).toUpperCase() +
                attr.getName().substring(1);
        Method m= cmbc.getClass().getMethod(methodName,String.class);
        //3 通过方法的反射操作方法
        m.invoke(cmbc,attr.getValue());
    }
    //剩余的不用组装attr参数 一共有四级
    Iterator twoDocument = oneEle.elementIterator();
    if(twoDocument.hasNext()) {
        while (twoDocument.hasNext()) {
            Element twoEle = (Element) twoDocument.next();

            Iterator threeDocument = twoEle.elementIterator();
            if (threeDocument.hasNext()) {
                while (threeDocument.hasNext()) {
                    Element threeEle = (Element) threeDocument.next();
                    //反射出二级对象
                    String twoName = threeEle.getParent().getName();
                    //反射数据
                    Method getThreeClassMethod = cmbc.getClass().getMethod("get"+twoName.substring(0, 1).toUpperCase()+twoName.substring(1));
                    Object objectThreeClass = getThreeClassMethod.invoke(cmbc);

                    Iterator fourDocument = threeEle.elementIterator();
                    if (fourDocument.hasNext()) {
                        //表示还有子节点
                        while (fourDocument.hasNext()) {
                            Element fourEle = (Element) fourDocument.next();

                            //获取三级对象
                            String threeName = fourEle.getParent().getName();
                            Method getFourClassMethod = objectThreeClass.getClass().getMethod("get"+threeName.substring(0, 1).toUpperCase()+threeName.substring(1));
                            Object objectFourClass = getFourClassMethod.invoke(objectThreeClass);

                            //把值反射到对象中
                            String methodName = "set"+fourEle.getName().substring(0, 1).toUpperCase() +
                                    fourEle.getName().substring(1);
                            Method m= objectFourClass.getClass().getMethod(methodName,String.class);
                            //通过方法的反射操作方法
                            m.invoke(objectFourClass,fourEle.getStringValue());
                        }
                    } else {
                        //没有子节点
                        String methodName = "set"+threeEle.getName().substring(0, 1).toUpperCase() +
                                threeEle.getName().substring(1);
                        Method m= objectThreeClass.getClass().getMethod(methodName,String.class);
                        //3 通过方法的反射操作方法
                        m.invoke(objectThreeClass,threeEle.getStringValue());
                    }
                }
            } else {
                String methodName = "set"+twoEle.getName().substring(0, 1).toUpperCase() +
                        twoEle.getName().substring(1);
                Method m= cmbc.getClass().getMethod(methodName,String.class);
                //3 通过方法的反射操作方法
                m.invoke(cmbc,twoEle.getStringValue());
            }
        }
    }
    System.out.println(cmbc);
} catch (DocumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
}

输出结果:

CMBC(trnCode=Xfer, security=none, lang=chs, header=100, version=100, responseHeader=CMBC.ResponseHeader(status=CMBC.ResponseHeader.Status(code=0, severity=info, message=ok, moreString=null), dtServer=2020-08-24 09:38:32, userKey=N, dtDead=, language=chs, moreString=null), xDataBody=CMBC.XDataBody(transfer=CMBC.XDataBody.Transfer(trnId=zhouyf, svrId=31301202008246046584784313000000, insId=00001, balance=59289497.37)), moreString=null)

可以看到XML已经被成功的解析到实体中了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值