Java 解析XML示例

要解析如下xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:FeatureDictionaryResponse xmlns="urn:xxx/Common/MetadataModel"
    xmlns:ns2="urn:xxx/Metadata">
    <ns2:Catalog id="xxxxx-xxxx-xxx-xxxx"/>
    <ns2:Config>
        <ProductSelections>
            <Series id="abc" selectable="false" compound="false" multi="false">
                <Feature id="Q0001"/>
                <Feature id="Q0002"/>
            </Series>
            <Series id="def" selectable="false" compound="false" multi="false">
                <Feature id="G0001"/>
            </Series>
        </ProductSelections>
    </ns2:Config>
</ns:FeatureDictionaryResponse>

一种方法是通过DOM解析方式实现,缺点是嵌套层次多导致代码不易读,修改起来麻烦。这里我们用类似反序列化方式来实现。

一、定义xml节点对应的类

 

 首先定义最内层节点对应的类:

package com.example.model;

import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Feature")
@Data
public class Feature {
    @XmlAttribute(name = "id")
    protected String id;
}

然后定义其父节点对应的类:

package com.example.model;

import lombok.Data;

import javax.xml.bind.annotation.*;
import java.util.List;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Series")
@Data
public class Series {
    @XmlAttribute
    protected String id;

    @XmlElement(name = "Feature")
    private List<Feature> features;
}

以此类推

package com.example.model;

import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement(name = "ProductSelections")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class ProductSelections {
    @XmlElement(name = "Series")
    protected List<Series> series;
}
package com.example.model;

import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ns2:Config")
@Data
public class Config {

    @XmlElement(name = "ProductSelections")
    protected ProductSelections productSelections;
}

最外层的类

package com.example.model;

import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "FeatureDictionaryResponse", namespace = "urn:xxx/Metadata")
@Data
public class FeatureDictionaryResponse {
    @XmlElement(name = "Config", namespace = "urn:xxx/Metadata")
    protected Config config;
}

由于xml中有自定义命名空间,所以我们需要添加一个package-info.java文件(在IDEA中直接添加会提示命名不合法,所以要手动创建出此文件),其内容如下

@XmlSchema(namespace = "urn:xxx/Common/MetadataModel",
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
        xmlns = {
                @XmlNs(prefix = "ns2", namespaceURI = "urn:xxx/Metadata")
        })
package com.example.model;

import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlNs;

最后创建一个XmlUtil.java(来源于网上其他博主),提供将字符串解析为对象的方法。

package com.example.common;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

public class XmlUtil {
    /**
     * 将对象直接转换成String类型的 XML输出
     * @param obj
     * @return
     */
    public static String convertToXml(Object obj) { // 创建输出流
        StringWriter sw = new StringWriter();
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();// 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            // 将对象转换成输出流形式的xml
            marshaller.marshal(obj, sw);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return sw.toString();
    }

    public static String mapToXml(Map<String, Object> map) {// 创建输出流
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>\n");
        //
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append("<").append(entry.getKey()).append(">");
            sb.append(entry.getValue().toString());
            sb.append("</").append(entry.getKey()).append(">\n");
        }
        sb.append("</xml>\n");
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    /**
     将String类型的xml转换成对象
     */
    public static <T> T convertToObj(String xmlStr, Class<T> clazz) {
        T xmlObject = null;
        // 进行将Xml转成对象的核心接口
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            StringReader sr = new StringReader(xmlStr);
            xmlObject = (T)
                    unmarshaller.unmarshal(sr);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return xmlObject;
    }
}

测试:

package com.example;

import com.example.common.XmlUtil;
import com.example.model.FeatureDictionaryResponse;

import java.io.BufferedReader;
import java.io.FileReader;

/**
 * @Author jian.yu
 * @Date 2021/2/4,0004 17:44
 * @Description
 */
public class App {
    public static void main(String[] args) {
        StringBuilder content = new StringBuilder();
        try {
            FileReader reader = new FileReader("D:\\Demo\\XmlResolve\\data.xml");
            BufferedReader br = new BufferedReader(reader);

            String line = br.readLine();
            while (line != null) {
                content.append(line);
                line = br.readLine();
            }
            br.close();
        } catch (Exception ex) {
            System.out.println(ex);
        }

        FeatureDictionaryResponse fd = XmlUtil.convertToObj(content.toString(), FeatureDictionaryResponse.class);
        System.out.println(fd.getConfig().getProductSelections().getSeries());
    }
}

输出结果:

 

 

源码:点此下载

posted @ 2021-02-05 16:03  梦醒江南·Infinite  阅读(364)  评论(0编辑  收藏  举报