XStream解析复杂XML(一)

http://my.oschina.net/kalo/blog/540852

在项目中遇到一个需求,需要解析接口中获取xml文件,该xml文件如下:

<?xml version='1.0' encoding='UTF-8' ?>
<PDMDataFile forceSend = "N" containerName = "Test_PRC1">
    <Part PartID = "VCI_20150714_001" Version = "---" Revision = "" ParentUUID = "">
        <Attributes>
            <PartName></PartName>
            <PartType>装配</PartType>
            <PartDesc></PartDesc>
            <PartUuid>5D0000077B</PartUuid>
            <CreatedBy></CreatedBy>
            <UpdatedBy>DES01</UpdatedBy>
            <Effectivity>1-5</Effectivity>
            <CreatedTime>2015-07-14 17:03:25</CreatedTime>
            <LastUpdated>2015-07-22 09:42:07</LastUpdated>
            <lifecycleState>UnderReview</lifecycleState>
            <ibaAttr Type = "String" CHName = "A" ENName = "DP_Maturaty">A</ibaAttr>
        </Attributes>
        <BomUses/>
    </Part>
    <Part PartID = "VCI_20150714_002" Version = "---" Revision = "6" ParentUUID = "">
        <Attributes>
            <PartName></PartName>
            <PartType>线路图</PartType>
            <PartDesc></PartDesc>
            <PartUuid>9C00000785</PartUuid>
            <CreatedBy></CreatedBy>
            <UpdatedBy>EV5ADM</UpdatedBy>
            <Effectivity>1-5</Effectivity>
            <CreatedTime>2015-07-14 18:21:16</CreatedTime>
            <LastUpdated>2015-07-14 18:21:17</LastUpdated>
            <lifecycleState>In Work</lifecycleState>
            <ibaAttr Type = "String" CHName = "B" ENName = "DP_Maturaty">B</ibaAttr>
        </Attributes>
        <BomUses>
            <Bom PartID = "VCI_20150609_003" PartUUID = "7300000788"/>
        </BomUses>
    </Part>
</PDMDataFile>


拿到这个xml文件大概分析了一下,完全可以把这个xml看作几个组合的类:

1. PDMDataFile > List<Part>

2. Part > Attributes | BomUses

3. BomUses > Bom

然后觉得也并不复杂。于是说干就干,风风火火的就写了这几个对应的类:

public class PDMDataFile {
    private List<Part> lstPart;
    public void setLstPart(List<Part> lstPart) {
        this.lstPart = lstPart;
    }
    public List<Part> getLstPart() {
        return lstPart;
    }
}
public class Part {
    public String partId;
    public String version;
    public String parentUuid;
    private Attributes atts;
    private BomUses bomUses;
    private List<Part> subPart; // 考虑子集合
    //......... 省略get set
}
public class BomUses {
    private List<Bom> lstBom;
    public void setLstBom(List<Bom> lstBom) {
        this.lstBom = lstBom;
    }
    public List<Bom> getLstBom() {
        return lstBom;
    }
}
public class Bom {
    private String partId;
    private String partUuid;
    public void setPartId(String partId) {
        this.partId = partId;
    }
    public String getPartId() {
        return partId;
    }
    public void setPartUuid(String partUuid) {
        this.partUuid = partUuid;
    }
    public String getPartUuid() {
        return partUuid;
    }
}


可是写到Attributes的时候,我犯傻了,这个类该怎么写呢?Attributes上面都是属性,还好说,它最下面这个ibaAttr,又包含属性,又包含text值,这算什么鬼?

<ibaAttr Type = "String" CHName = "B" ENName = "DP_Maturaty">B</ibaAttr>

给接口项目的人员联系了一下,确定这个节点写在这里是正确的,并且有可能还有很多个。很多个?嗯,那好吧,干脆写到Attributes里面,做一个List算了。于是,Attributes类也最终确定:

public class Attributes {
    private String partName;
    private String partDesc;
    private String partType;
    private String partUuid;
    private String updatedBy;
    private String effectivity;
    private String lifeCycleState;
    private String dpMaturat;
    private String createdBy;
    private String createdTime;
    private String lastUpdated;
    private List<IbaAttr> lstIbaAttr;
    // 省略get set
}
public class IbaAttr {
    private String type;
    private String chname;
    private String enname;
    private String text;
    // 省略get set
}


既然 IbaAttr 既有 属性,又有text,那我干脆给你添加一个text字段好了,免得到时候我没地方存text。

到这里面,按照我之前做过的方式,直接用XStream来解析就好了。可是在实际解析的时候,我发现,

<ibaAttr Type = "String" CHName = "B" ENName = "DP_Maturaty">B</ibaAttr>


IbaAttr 节点如上,没有一个现有的方法能取到text。之前没遇到过啊!马上搜了一下,哈哈,有了。

http://www.jb51.cc/article/p-xylzfvcs-mk.html

按照如上链接讲的,立马加上自定义转化类:

public class FieldDtoConvertor implements Converter {
    public boolean canConvert(@SuppressWarnings("rawtypes") final Class clazz) {
        return clazz.equals(IbaAttr.class);
    }

    public void marshal(Object value,HierarchicalStreamWriter writer,MarshallingContext context) {
        final IbaAttr fieldDto = (IbaAttr) value;
        writer.addAttribute(fieldDto.getText(),fieldDto.getText());
    }

    public Object unmarshal(HierarchicalStreamReader reader,UnmarshallingContext context) {        
        IbaAttr result = new IbaAttr();
        result.setChname(reader.getAttribute("CHName"));
        result.setEnname(reader.getAttribute("ENName"));
        result.setType(reader.getAttribute("Type"));        
        result.setText(reader.getValue());
        return result;
    }
}


就是这么简单,好了,整个解析就基本上完成了。如下是xstream解析对应代码

public PDMDataFile deserializeFromXML(String filePath) {        
    XStream xstream = new XStream(new DomDriver());
    xstream.registerConverter(new FieldDtoConvertor());
    xstream.alias("PDMDataFile",PDMDataFile.class);
    xstream.addImplicitCollection(PDMDataFile.class,"lstPart");
        
    xstream.alias("Part",Part.class);        
    xstream.aliasAttribute(Part.class,"partId","PartID");
    xstream.aliasAttribute(Part.class,"version","Version");
    xstream.aliasAttribute(Part.class,"parentUuid","ParentUUID");
        
    xstream.aliasField("Attributes",Part.class,"atts");
    xstream.aliasField("BomUses","bomUses");
        
    xstream.alias("Attributes",Attributes.class);
    xstream.aliasField("PartName",Attributes.class,"partName");
    xstream.aliasField("PartType","partType");
    xstream.aliasField("PartDesc","partDesc");
    xstream.aliasField("PartUuid","partUuid");
    xstream.aliasField("UpdatedBy","updatedBy");
    xstream.aliasField("Effectivity","effectivity");
    xstream.aliasField("lifecycleState","lifeCycleState");        
    xstream.aliasField("CreatedBy","createdBy");
    xstream.aliasField("CreatedTime","createdTime");
    xstream.aliasField("LastUpdated","lastUpdated");
        
    xstream.addImplicitCollection(Attributes.class,"lstIbaAttr");        
        
    xstream.alias("ibaAttr",IbaAttr.class);
    xstream.aliasAttribute(IbaAttr.class,"type","Type");
    xstream.aliasAttribute(IbaAttr.class,"chname","CHName");
    xstream.aliasAttribute(IbaAttr.class,"enname","ENName");
        
    xstream.alias("BomUses",BomUses.class);
    xstream.addImplicitCollection(BomUses.class,"lstBom");
        
    xstream.alias("Bom",Bom.class);
    xstream.useAttributeFor("partId",Bom.class);
    xstream.useAttributeFor("partUuid",Bom.class);
    xstream.aliasAttribute(Bom.class,"PartID");
    xstream.aliasAttribute(Bom.class,"partUuid","PartUUID");        

    PDMDataFile result = new PDMDataFile();
    try {
        FileInputStream fis = new FileInputStream(filePath);
        result = (PDMDataFile) xstream.fromXML(fis);
    } catch (Exception ex) {
        ex.printStackTrace();
        return null;
    }
    return result;
}

相关文章

引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满足人的生产生活需要而产生的。具体...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
http://blog.jobbole.com/79252/ 引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满...
(点击上方公众号,可快速关注) 公众号:smart_android 作者:耿广龙|loonggg 点击“阅读原文”,可查看...
一、xml与xslt 相信所有人对xml都不陌生,其被广泛的应用于数据数据传输、保存与序列化中,是一种极为强...