JAVA JAXB 解析XML嵌套子节点为字符串

问题背景

近期项目中涉及接收xml入参数据自动映射到java实体,xml数据是以@RequestBody形式接收,通过javax.xml.bind.annotation注解来实现自动转换,但是在xml数据中有一个子节点内的数据是非固定格式的数据,里面的各个元素的标签是动态的而不是固定的,就需要将这个子节点内数据当做一个字符串来解析并映射到实体的一个属性上,查阅资料后才找到一种解决办法。

目前的解决途径

通过目标字段增加@XmlJavaTypeAdapter自定义xml到java类型的适配器来实现,话不多说,上代码

实体类

package org.example;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

/**
 * @Title: Company
 * @Package org.example
 * @Description: TODO
 * @Author MYF
 * @Date 2022/12/1 21:24
 * @Version V1.0
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Company {

    private String businessName;

    private String orgType;

    @XmlJavaTypeAdapter(CustomAdapter.class)
    private String legalExt;

    public String getBusinessName() {
        return businessName;
    }

    public void setBusinessName(String businessName) {
        this.businessName = businessName;
    }

    public String getOrgType() {
        return orgType;
    }

    public void setOrgType(String orgType) {
        this.orgType = orgType;
    }

    public String getLegalExt() {
        return legalExt;
    }

    public void setLegalExt(String legalExt) {
        this.legalExt = legalExt;
    }
}

自定义xml到java类型的适配器

本例中只实现了xml到java类型的转换也就是下放代码中的 unmarshal 方法

package org.example;

import org.w3c.dom.Element;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;

/**
 * @Title: CustomAdapter
 * @Package org.example
 * @Description: TODO
 * @Author MYF
 * @Date 2022/12/1 21:26
 * @Version V1.0
 */
public class CustomAdapter extends XmlAdapter<Object, String> {
    @Override
    public String unmarshal(Object xmlObj) throws Exception {
        Element element = (Element)xmlObj;
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Transformer transformer = transFactory.newTransformer();
        StringWriter buffer = new StringWriter();
        /**是否省略xml的头部声明**/
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        /**转换成字符串时应用的编码**/
        transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
        /**可以理解为压缩xml,不美化格式**/
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0");
        transformer.transform(new DOMSource(element),
                new StreamResult(buffer));
        String xmlStr = buffer.toString();
        return xmlStr;
    }

    @Override
    public Object marshal(String v) throws Exception {
        return v;
    }
}

测试类

注:本例中测试xml中的数据为假数据

package org.example;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.Reader;
import java.io.StringReader;

public class TestXmlTransform {
    public static void main(String[] args) throws Exception {
        /**
         * 示例xml结构如下,其中legalExt下为
         * <company>
         *     <businessName>北京神宇科技公司</businessName>
         *     <orgType>02</orgType>
         *     <legalExt>
         *         <legalName>赵公子</legalName>
         *         <legalType>自然人</legalType>
         *         <legalIdCard>假装身份证号</legalIdCard>
         *         <dynamicKey1>dynamicVal1</dynamicKey1>
         *         <dynamicKey2>dynamicVal2</dynamicKey2>
         *         <dynamicKeyN>dynamicValN</dynamicKeyN>
         *     </legalExt>
         * </company>
         * 其中dynamicKey1~dynamicKeyN为动态标签,可能随实际业务不同而不同
         * **/
        String xmlStr = "<company><businessName>北京神宇科技公司</businessName><orgType>02</orgType><legalExt><legalName>赵公子</legalName><legalType>自然人</legalType><legalIdCard>假装身份证号</legalIdCard><dynamicKey1>dynamicVal1</dynamicKey1><dynamicKey2>dynamicVal2</dynamicKey2><dynamicKeyN>dynamicValN</dynamicKeyN></legalExt></company>";
        Reader reader = null;
        JAXBContext context = JAXBContext.newInstance(Company.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        reader = new StringReader(xmlStr);
        Company company = (Company)unmarshaller.unmarshal(reader);
        System.out.println(company.getLegalExt());
        if (reader != null) {
            reader.close();
        }
    }
}

测试类执行结果
实际代码输出为一行,为方便贴图借用hutoo的XmlUtil格式化了一下
在这里插入图片描述

最后

以上的代码已经打包到CSDN—→传送门
时间有限没在继续寻找更好的解决方案,如有更好的解决方式还望各位朋友留言相告!
PS:第一次编写这种文章,各位浅喷~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值