1. 程式人生 > >使用XStream註解處理複雜xml的屬性及資料集合(xml轉物件)

使用XStream註解處理複雜xml的屬性及資料集合(xml轉物件)

1. XStream簡介

2.簡單使用

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.10</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId
>
lombok</artifactId> <version>${lombok.version}</version> </dependency>

3.正常xml的解析

注意程式碼中xmlString都代表當前小結裡面的xml字串

<User>
  <userName>lanweihong</userName>
  <email>[email protected]</email>
</User>

物件

public class User {

    private
String userName; private String email; public User(String userName, String email) { this.userName = userName; this.email = email; } }

執行

public static void main(String[] args) {
    XStream xStream = new XStream();
    xStream.alias("User", User.class);
    String xml = xmlString;
    //轉物件
User user = (User)xStream.fromXML(xml); System.out.println(user.toString()); }

輸出文字為:

User:{userName=lanweihong,[email protected].com}

4.有點不正常xml的解析

一個看著比較“正常”的帶有集合的xml
1. carInfos做為根元素,其子元素是由N個carInfo組成的集合,每個carInfo元素描述一個物件資訊。
2. carInfo的子元素,每個tag做為屬性名,tag所包含的txt做為屬性值。

<carInfos dwName="sys.common.new_vehicle_DW">
    <carInfo index="1">
        <VehicleId>FTBAUD0088</VehicleId>
        <VehicleName>福克斯CAF7163B5轎車</VehicleName>
        <Remark>兩廂 雙離合 舒適型 國Ⅴ</Remark>
        <VehiclePrice>101800</VehiclePrice>
    </carInfo>
    <carInfo index="2">
        <VehicleId>FTBAUD0078</VehicleId>
        <VehicleName>福克斯CAF7163B5轎車</VehicleName>
        <Remark>兩廂 雙離合 風尚型 國Ⅴ</Remark>
        <VehiclePrice>113800</VehiclePrice>
    </carInfo>
    <carInfo index="3">
        <VehicleId>FTBAUD0097</VehicleId>
        <VehicleName>福克斯CAF7163B5轎車</VehicleName>
        <Remark>兩廂 雙離合 智行版 風尚型 國Ⅴ</Remark>
        <VehiclePrice>115800</VehiclePrice>
    </carInfo>
</carInfos>

與xml元素對應的Java類
對應carInfos元素

@XStreamAlias("carInfos")//對應carInfos元素
public class CarInfos {

    @XStreamAsAttribute
    private String dwName;//對應carInfos元素的dwName屬性

    @XStreamImplicit(itemFieldName = "carInfo")
    private List<CarInfo> carInfoList = new ArrayList<CarInfo>();//對應N個carInfo元素組成的集合

    //省略getter/setter方法
}

對應carInfo元素

@XStreamAlias("carInfo")//對應carInfo元素
public class CarInfo {

    @XStreamAsAttribute
    private String index;//對應carInfo的index屬性

    @XStreamAlias("VehicleId")
    private String vehicleId;//對應carInfo的VehicleId子元素

    @XStreamAlias("VehicleName")
    private String VehicleName;//對應carInfo的VehicleName子元素

    @XStreamAlias("Remark")
    private String remark;//對應carInfo的Remark子元素

    @XStreamAlias("VehiclePrice")
    private String vehiclePrice;//對應carInfo的VehiclePrice子元素

    //省略getter/setter方法
}

解析xml

public static void main(String[] args) throws Exception {
    File dataXml = readXml();//讀取xml
    XStream xstream = new XStream(new DomDriver());//建立Xstram物件
    xstream.autodetectAnnotations(true);
    xstream.processAnnotations(CarInfos.class);
    CarInfos carInfos = (CarInfos) xstream.fromXML(dataXml);
    //列印物件
    System.out.printf("CarInfos dwName:%s\n", carInfos.getDwName());
    for (CarInfo carInfo : carInfos.getCarInfoList()) {
        System.out.printf("\tCarInfo index:%s\n", carInfo.getIndex());
        System.out.printf("\tCarInfo VehicleId:%s\n", carInfo.getVehicleId());
        System.out.printf("\tCarInfo VehicleName:%s\n", carInfo.getVehicleName());
        System.out.printf("\tCarInfo VehiclePrice:%s\n", carInfo.getVehiclePrice());
        System.out.printf("\tCarInfo Remark:%s\n", carInfo.getRemark());
    }
    //將物件轉為xml,再次列印
    String resultXml = xstream.toXML(carInfos);
    System.out.printf("=======================\n" + resultXml);
}

5.更加不正常xml的解析

一個“有點彆扭”的xml

特點是carInfo元素下是多個attribute元素的集合。但是很明顯,每個attribute元素的屬性name的值,都本應該是carInfo元素的子元素的tagName。

<carInfos dwName="sys.common.new_vehicle_DW">
    <carInfo index="1">
        <attribute name="VehicleId">FTBAUD0088</attribute>
        <attribute name="VehicleName">福克斯CAF7163B5轎車</attribute>
        <attribute name="Remark">兩廂 雙離合 舒適型 國Ⅴ</attribute>
        <attribute name="VehiclePrice">101800</attribute>
    </carInfo>
    <carInfo index="2">
        <attribute name="VehicleId">FTBAUD0078</attribute>
        <attribute name="VehicleName">福克斯CAF7163B5轎車</attribute>
        <attribute name="Remark">兩廂 雙離合 風尚型 國Ⅴ</attribute>
        <attribute name="VehiclePrice">113800</attribute>
    </carInfo>
    <carInfo index="3">
        <attribute name="VehicleId">FTBAUD0097</attribute>
        <attribute name="VehicleName">福克斯CAF7163B5轎車</attribute>
        <attribute name="Remark">兩廂 雙離合 智行版 風尚型 國Ⅴ</attribute>
        <attribute name="VehiclePrice">115800</attribute>
    </carInfo>
</carInfos>

與xml元素對應的Java類
根據attribute元素,新建一個CarAttr類。

注意這裡使用到@XStreamCoverter註解。 而且沒有對成員變數添加註解。

@XStreamAlias("attribute")
@XStreamConverter(CarAttrConverter.class)
public class CarAttr {

    //沒有使用@XStreamAsAttribute註解
    private String name;

    //沒有使用註解
    private String value;

    //省略getter/setter方法

對CarInfo類進行修改,因為carInfo元素下是多個attribute元素,所以定義了一個List集合。如同CarInfos與CarInfo的關係。

@XStreamAlias("carInfo")
public class CarInfo {

    @XStreamAsAttribute
    private String index;

    @XStreamImplicit(itemFieldName = "attribute")
    private List<CarAttr> attrs = new ArrayList<CarAttr>();

    //省略getter/setter方法
}

定義CarAttr轉換類(這個是可有可無的類)

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class CarAttrConverter implements Converter {

    @Override
    public boolean canConvert(Class type) {
        return type.equals(CarAttr.class);//轉換條件
    }

    /**
     * 將java物件轉為xml時使用
     */
    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        CarAttr attr = (CarAttr) source;
        // writer.startNode("attribute");
        writer.addAttribute("name", attr.getName());
        writer.setValue(attr.getValue());
        // writer.endNode();
    }

    /**
     * 將xml轉為java物件使用
     */
    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        CarAttr a = new CarAttr();// 在解析attribute元素時,先建立一個CarAttr物件
        a.setName(reader.getAttribute("name"));// 將attribute元素的name屬性設定為CarAttr物件的name屬性值
        a.setValue(reader.getValue());// 將attribute元素的txt值設定為CarAttr物件的value值
        return a;
    }
}

解析xml

public static void main(String[] args) throws Exception {
        File dataXml = readXml();
        XStream xstream = new XStream(new DomDriver());
        xstream.autodetectAnnotations(true);
        xstream.processAnnotations(CarInfos.class);
        CarInfos carInfos = (CarInfos) xstream.fromXML(dataXml);
        //列印物件
        System.out.printf("CarInfos dwName:%s\n", carInfos.getDwName());
        for (CarInfo carInfo : carInfos.getCarInfoList()) {
            System.out.printf("\tCarInfo index:%s\n", carInfo.getIndex());
            for (CarAttr ca : carInfo.getAttrs()) {
                System.out.printf("\t\tCarAttr name:%s,value:%s\n", ca.getName(), ca.getValue());
            }
        }
        String resultXml = xstream.toXML(carInfos);
        System.out.printf("=======================\n" + resultXml);
    }

兩個xml的解析方法沒有區別,只是在列印解析出的物件時,稍有不同。主要區別在於根據attribute元素,新增加了CarAttr類的定義,及與CarAttr類對應CarAttrConverter轉換類的使用。

6.非常不正常xml的解析

<dlineage>
   <relation id="3" type="dataflow">
      <target coordinate="[1,27],[1,31]" column="NAME" id="5" parent_id="1" parent_name="TABLEA"/>
      <source coordinate="[1,27],[1,31]" column="NAME" id="1" parent_id="2" parent_name="B"/>
   </relation>
   <relation id="4" type="dataflow">
      <target coordinate="[1,32],[1,35]" column="AGE" id="6" parent_id="1" parent_name="TABLEA"/>
      <source coordinate="[1,32],[1,35]" column="AGE" id="2" parent_id="2" parent_name="B"/>
   </relation>
   <table name="TABLEA" id="1" type="table" coordinate="[1,13],[1,19]">
      <column name="NAME" id="5" coordinate="[1,27],[1,31]"/>
      <column name="AGE" id="6" coordinate="[1,32],[1,35]"/>
   </table>
   <table name="B" id="2" type="table" coordinate="[1,42],[1,43]">
      <column name="NAME" id="1" coordinate="[1,27],[1,31]"/>
      <column name="AGE" id="2" coordinate="[1,32],[1,35]"/>
   </table>
</dlineage>

這裡有倆坑
1. 坑1:dlineage物件我的Dlinage(一個解析血緣的工具類收費的))已經儲存,不能定義這個
2. 坑2:parent_id parent_name 不識別帶有橫崗的屬性

針對這兩個問題對xml進行預處理

xmlString = xmlString.replaceAll("dlineage","DlineageEntity");
xmlString = xmlString.replaceAll("parent_id","parentId");
xmlString = xmlString.replaceAll("parent_name","parentName");

建立實體類

@Data
@XStreamAlias("DlineageEntity")//對應dlineage元素
public class DlineageEntity {

    // 對應relation
    @XStreamImplicit(itemFieldName = "relation")
    private List<Relation> relation;

    // 對應table
    @XStreamImplicit(itemFieldName = "table")
    private List<Table> table;

}
@Data
@XStreamAlias("relation")  // 對應relation
public class Relation {

    // 對應 id 屬性
    @XStreamAsAttribute
    private String id;
    // 對應 type 屬性
    @XStreamAsAttribute
    private String type;

    // 對應 target 子元素
    @XStreamImplicit(itemFieldName = "target")
    private List<Target> target ;
    // 對應 source 子元素
    @XStreamImplicit(itemFieldName = "source")
    private List<Source> source ;

}
@Data
@XStreamAlias("target") // 對應 target
public class Target {

    // 對應 coordinate 屬性
    @XStreamAsAttribute
    private String coordinate;
    // 對應 column 屬性
    @XStreamAsAttribute
    private String column;
    // 對應 id 屬性
    @XStreamAsAttribute
    private String id;
    // 對應 parentId 屬性
    @XStreamAsAttribute
    private String parentId;
    // 對應 parentName 屬性
    @XStreamAsAttribute
    private String parentName;

}
@Data
@XStreamAlias("source")
public class Source {

    @XStreamAsAttribute
    private String coordinate;
    @XStreamAsAttribute
    private String column;
    @XStreamAsAttribute
    private String id;
    @XStreamAsAttribute
    private String parentId;
    @XStreamAsAttribute
    private String parentName;

}
@Data
@XStreamAlias("table")
public class Table {

    @XStreamAsAttribute
    private String name;
    @XStreamAsAttribute
    private String id;
    @XStreamAsAttribute
    private String type;
    @XStreamAsAttribute
    private String coordinate;

    @XStreamImplicit(itemFieldName = "column")
    private List<Column> column;
}
@Data
@XStreamAlias("column")
public class Column {

    @XStreamAsAttribute
    private String name;
    @XStreamAsAttribute
    private String id;
    @XStreamAsAttribute
    private String coordinate;


}

解析物件

private static void makeBlood(String result ) {
        result = result.replaceAll("dlineage","DlineageEntity");
        result = result.replaceAll("parent_id","parentId");
        result = result.replaceAll("parent_name","parentName");

        System.out.println( "===>"+result );

        XStream xStream = new XStream();
        xStream.autodetectAnnotations(true);
        xStream.processAnnotations(DlineageEntity.class);
        DlineageEntity carInfos = (DlineageEntity) xStream.fromXML(result);

        System.out.println(carInfos.toString());
    }

結果

DlineageEntity(
    relation=[
        Relation(
            id=3, type=dataflow, 
            target=[ Target( coordinate=[1,27],[1,31], column=NAME, id=5, parentId=1, parentName=TABLEA)], 
            source=[Source(coordinate=[1,27],[1,31], column=NAME, id=1, parentId=2, parentName=B)]
        ),  
        Relation(id=4, type=dataflow, 
            target=[Target(coordinate=[1,32],[1,35], column=AGE, id=6, parentId=1, parentName=TABLEA)], 
            source=[Source(coordinate=[1,32],[1,35], column=AGE, id=2, parentId=2, parentName=B)]
        ) 
],  
table=[ 
     Table(name=TABLEA, id=1, type=table, coordinate=[1,13],[1,19], 
         column=[ 
             Column(name=NAME, id=5, coordinate=[1,27],[1,31]), 
             Column(name=AGE, id=6, coordinate=[1,32],[1,35])
             ]
    ), 
     Table(name=B, id=2, type=table, coordinate=[1,42],[1,43], 
         column=[ 
             Column(name=NAME, id=1, coordinate=[1,27],[1,31]), 
             Column(name=AGE, id=2, coordinate=[1,32],[1,35])
         ]
        )
    )

相關推薦

使用XStream註解處理複雜xml屬性資料集合xml物件

1. XStream簡介 2.簡單使用 <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactI

從Storm到Flink:大資料處理的開源系統程式設計模型文末福利

本文節選自CCF大資料教材系列叢書之《大資料處理》,本書由華中科技大學金海教授主編,包括大資料處理基礎技術、大資料處理程式設計與典型應用處理、大資料處理系統與優化三個方面。本教材以大資料處理程式設計為核心,從基礎、程式設計到優化等多個方面對大資料處理技術進行系統介紹,使得讀者能

ETH&EOS開發資源工具集合完整彙總版

ETH開發資源篇一、開發語言• Solidity - 官方推薦以太坊智慧合約開發語言,也是目前最為主流的智慧合約語言• Bamboo - 是一種將智慧合約描述為有限狀態機的語言,把智慧合約看成一個狀態和交易的函式,同時生成一個新的狀態• Vyper - 一種類 python 的面向合約程式語言,專注於以太坊虛

ETH&EOS開發資源工具集合完整彙總版

ETH開發資源篇 一、開發語言 ·         Solidity - 官方推薦以太坊智慧合約開發語言,也是目前最為主流的智慧合約語言 ·         Bamboo - 是一種將智慧合約描述為有限狀態機的語言,把智慧合約看成一個狀態和交易的函式,同時生成一個新的狀態

JavaScript之ES6中解構原理注意事項陣列和物件

//ES6中的解構原理(常用型別):   //陣列解構: //陣列的元素是按次序排列的,變數的取值由它的位置決定; let [a,b,c] = [1,2,3]; console.log(a,b,c) //結果為: 1,2,3;   //物件解構變數同名(

資料 巨量資料集合IT行業術語

大資料(large data),指無法在一定時間範圍內用常規軟體工具進行捕捉、管理和處理的資料集合,是需要新處理模式才能具有更強的決策力、洞察發現力和流程優化能力的海量、高增長率和多樣化的資訊資產。[1] 在維克托·邁爾-舍恩伯格及肯尼斯·庫克耶編寫的《大資

自定義控制元件三部曲之動畫篇——alpha、scale、translate、rotate、set的xml屬性用法

前言:這幾天做客戶回訪,感觸很大,使用者只要是留反饋資訊,總是一種恨鐵不成鋼的心態,想用你的app,卻是因為你的技術問題,讓他們不得不放棄,而你一個回訪電話卻讓他們盡釋前嫌,當最後把手機號留給他們以便隨時溝通的時候,總會發來一條條的鼓勵簡訊,讓我不自主的開始內疚。哎,多麼可愛

:定義控制元件三部曲之動畫篇——alpha、scale、translate、rotate、set的xml屬性用法

前言:這幾天做客戶回訪,感觸很大,使用者只要是留反饋資訊,總是一種恨鐵不成鋼的心態,想用你的app,卻是因為你的技術問題,讓他們不得不放棄,而你一個回訪電話卻讓他們盡釋前嫌,當最後把手機號留給他們以便隨時溝通的時候,總會發來一條條的鼓勵簡訊,讓我不自主的開始內疚。哎,多麼

Android自定義控制元件:動畫類----alpha、scale、translate、rotate、set的xml屬性用法

二、下面我們逐個講講每個標籤的屬性及用法 1、scale標籤——調節尺寸 1> 自有屬性 scale標籤是縮放動畫,可以實現動態調控制元件尺寸的效果,有下面幾個屬性: android:fromXScale    起始的X方向上相對自身的縮放比例,浮點值,比如1.0代表自身無變化,

Spring入門bean配置XML註解

目錄 一、概述 一、概述 Spring是一個開放原始碼的設計層面框架,他解決的是業務邏輯層和其他各層的鬆耦合問題,因此它將面向介面的程式設計思想貫穿整個系統應用。Spring是於2003

Animation 動畫詳解——alpha、scale、translate、rotate、set的xml屬性用法

Android的animation由四種類型組成:alpha、scale、translate、rotate,對應android官方文件地址:《Animation Resources》 1、XML配置檔案中 alpha 漸變透明度動畫效果 scale 漸變尺

js入門 關於js屬性及其資料型別詳解

1. js的本質就是處理資料。資料來自於後臺的資料庫。 所以變數就起到一個臨時儲存資料的作用。 ECMAScript制定了js的資料型別。 資料型別有哪些? 1. 字串   String 2. 數字    Number

如何在串列埠除錯助手上,使用printf()函式顯示十進位制的資料漢字說明c語言版

估計很多人和我一樣,很想直接在串列埠除錯助手上顯示十進位制資料,我最近在做一個專案,當然本人也是小白,但這個問題已經被我解決了,希望幫助需要的人。 我們都知道,串列埠助手一般都只能顯示十六進位制資料和字元,如果我們想將控制器的實時資料通過串列埠傳送到上位機,方便監測,最好直接顯示十進位制資料。廢

《影象處理、分析與機器視覺》第4版閱讀筆記——第四章 影象分析的資料結構

4.1 影象資料表示的層次 共分為四個層次: 最底層的表示:圖示影象(iconic images),由含有原始資料的影象組成,原始資料也就是畫素亮度資料的整數矩陣。(預處理的部分) 第二層的表示:分割影象(segmented images)。 第三層:幾何表示(geo

資料結構】二叉樹的構建遍歷遞迴演算法

題目描述: 編一個程式,讀入使用者輸入的一串先序遍歷字串,根據此字串建立一個二叉樹(以指標方式儲存)。 例如如下的先序遍歷字串: ABC##DE#G##F### 其中“#”表示的是空格,空格字元代表空樹。建立起此二叉樹以後,再對二叉樹進行中序遍歷,輸出遍歷結果。 具體程式

用Java+xml配置方式實現Spring資料事務程式設計式事務

一、用Java配置的方式 1、實體類: Role  public class Role { private int id; private String roleName; private String note; @Override

用AOP攔截自定義註解並獲取註解屬性與上下文引數基於Springboot框架

目錄 AOP可以用於日誌的設計,這樣話就少不了要獲取上下文的資訊,博主在設計日誌模組時考慮了一下此法,整理了一下如何用AOP來攔截你自定義的註解。 自定義註解 首先先自定義一個註解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNT

pytorch 資料處理:定義自己的資料集合

資料處理 版本1 #資料處理 import os import torch from torch.utils import data from PIL import Image import numpy as np #定義自己的資料集合 class D

ssm中mybatis處理資料庫mysql與pojo屬性中型別不一致stringdate

        一般在表設計的時候會考慮到資料庫欄位型別和java中屬性一致的問題,但是也有可能會出現一些情況導致型別不一致的問題,比如:二次開發中需求更改等。此時資料庫和java中的程式碼不能隨便更改,所以考慮的思路是通過typeHandler作為中間體來把型別轉換。  

計算機視覺筆記資料整理含影象分割、目標檢測小方向學習

前言 1、簡單聊聊: 在我腦海中我能通過這些年聽到的技術名詞來感受到技術的更新及趨勢,這種技術發展有時候我覺得連關注的腳步都趕不上。簡單回顧看看,從我能聽到的技術名詞來感受,最開始耳聞比較多「雲端計算」這玩意,後來聽到比較多的是「資料探勘」,當時想著等考上研也要