日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

XStream – XStreamely使用Java中的XML数据的简便方法

發(fā)布時(shí)間:2023/12/3 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 XStream – XStreamely使用Java中的XML数据的简便方法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有時(shí)候,我們不得不處理XML數(shù)據(jù)。 而且大多數(shù)時(shí)候,這不是我們一生中最快樂(lè)的一天。 甚至有一個(gè)術(shù)語(yǔ)“ XML地獄”描述了程序員必須處理許多難以理解的XML配置文件時(shí)的情況。 但是,不管喜歡與否,有時(shí)我們別無(wú)選擇,這主要是因?yàn)榭蛻舳说恼f(shuō)明中提到了諸如“使用以XML文件編寫的配置”之類的內(nèi)容。 在這種情況下, XStream帶有非常酷的功能,這些功能使處理XML的痛苦減輕了。

總覽

XStream是一個(gè)小型庫(kù),用于在Java對(duì)象和XML之間序列化數(shù)據(jù)。 它重量輕,體積小,具有漂亮的API,最重要的是,它可以與自定義注釋一起使用,也可以不包含不屬于Java類所有者的自定義注釋。

第一個(gè)例子

假設(shè)我們需要從xml文件加載配置:

<config><inputFile>/Users/tomek/work/mystuff/input.csv</inputFile><truststoreFile>/Users/tomek/work/mystuff/truststore.ts</truststoreFile><keystoreFile>/Users/tomek/work/mystuff/CN-user.jks</keystoreFile><!-- ssl stores passwords--><truststorePassword>password</truststorePassword><keystorePassword>password</keystorePassword><!-- user credentials --><user>user</user><password>secret</password> </config>

我們想將其加載到Configuration對(duì)象中:

public class Configuration {private String inputFile;private String user;private String password;private String truststoreFile;private String keystoreFile;private String keystorePassword;private String truststorePassword;// getters, setters, etc. }

所以基本上我們要做的是:

FileReader fileReader = new FileReader("config.xml"); // load our xml file XStream xstream = new XStream(); // init XStream// define root alias so XStream knows which element and which class are equivalentxstream.alias("config", Configuration.class); Configuration loadedConfig = (Configuration) xstream.fromXML(fileReader);

僅此而已

更嚴(yán)重的事情

好的,但是前面的示例非常基礎(chǔ),因此現(xiàn)在讓我們做一些更復(fù)雜的事情:由真實(shí)WebService返回的真實(shí)XML。

<DATA xmlns=""><BAN><UPDATED_AT>2013-03-09</UPDATED_AT><TROUBLEMAKER><NAME1>JOHN</NAME1><NAME2>EXAMPLE</NAME2><AGE>24</AGE><NUMBER>ASD123123</NUMBER></TROUBLEMAKER></BAN><BAN><UPDATED_AT>2012-03-10</UPDATED_AT><TROUBLEMAKER><NAME1>ANNA</NAME1><NAME2>BAKER</NAME2><AGE>26</AGE><NUMBER>AXN567890</NUMBER></TROUBLEMAKER></BAN><BAN><UPDATED_AT>2010-12-05</UPDATED_AT><TROUBLEMAKER><NAME1>TOM</NAME1><NAME2>MEADOW</NAME2><NUMBER>SGH08945</NUMBER><AGE>48</AGE></TROUBLEMAKER></BAN> </DATA>

我們這里提供的是用XML編寫的簡(jiǎn)單禁令清單。 我們希望將其加載到Ban對(duì)象的集合中。 因此,讓我們準(zhǔn)備一些類(省略getters / setters / toString):

public class Data {private List bans = new ArrayList(); }public class Ban {private String dateOfUpdate;private Person person; }public class Person {private String firstName;private String lastName;private int age;private String documentNumber; }

如您所見,XML和Java類之間存在一些命名和類型不匹配的問(wèn)題(例如,字段名1-> firstName,dateOfUpdate是String而不是Date),但這是出于某些示例目的。 因此,這里的目標(biāo)是解析XML并使用包含正確數(shù)據(jù)的Ban實(shí)例的填充集合來(lái)獲取Data對(duì)象。 讓我們看看如何實(shí)現(xiàn)它。

解析注釋

首先,更簡(jiǎn)單的方法是使用注釋。 這是在我們可以修改將XML映射到的Java類的情況下的建議方法。
因此,我們有:

@XStreamAlias("DATA") // maps DATA element in XML to this class public class Data {// Here is something more complicated. If we have list of elements that are // not wrapped in a element representing a list (like we have in our XML: // multiple <ban> elements not wrapped inside <bans> collection, // we have to declare that we want to treat these elements as an implicit list // so they can be converted to List of objects. @XStreamImplicit(itemFieldName = "ban") private List bans = new ArrayList(); }@XStreamAlias("BAN") // another mapping public class Ban {/*We want to have different field names in Java classes sowe define what element should be mapped to each field*/@XStreamAlias("UPDATED_AT") // private String dateOfUpdate;@XStreamAlias("TROUBLEMAKER")private Person person; }@XStreamAlias("TROUBLEMAKER") public class Person {@XStreamAlias("NAME1")private String firstName;@XStreamAlias("NAME2")private String lastName;@XStreamAlias("AGE") // String will be auto converted to int valueprivate int age;@XStreamAlias("NUMBER")private String documentNumber;

實(shí)際的解析邏輯非常簡(jiǎn)短:

FileReader reader = new FileReader("file.xml"); // load fileXStream xstream = new XStream();xstream.processAnnotations(Data.class); // inform XStream to parse annotations in Data classxstream.processAnnotations(Ban.class); // and in two other classes... xstream.processAnnotations(Person.class); // we use for mappingsData data = (Data) xstream.fromXML(reader); // parse// Print some data to console to see if results are correctSystem.out.println("Number of bans = " + data.getBans().size());Ban firstBan = data.getBans().get(0);System.out.println("First ban = " + firstBan.toString());

如您所見,注釋非常易于使用,因此最終代碼非常簡(jiǎn)潔。 但是在無(wú)法修改映射類的情況下該怎么辦? 我們可以使用不需要對(duì)表示XML數(shù)據(jù)的Java類進(jìn)行任何修改的其他方法。

解析無(wú)注釋

當(dāng)我們無(wú)法用注解充實(shí)我們的模型類時(shí),還有另一種解決方案。 我們可以使用XStream對(duì)象的方法定義所有映射詳細(xì)信息:

FileReader reader = new FileReader("file.xml"); // three first lines are easy, XStream xstream = new XStream(); // same initialisation as in the xstream.alias("DATA", Data.class); // basic example abovexstream.alias("BAN", Ban.class); // two more aliases to map... xstream.alias("TROUBLEMAKER", Person.class); // between node names and classes// We want to have different field names in Java classes so// we have to use aliasField(<fieldInXml>, <mappedJavaClass>, <mappedFieldInJavaClass>)xstream.aliasField("UPDATED_AT", Ban.class, "dateOfUpdate"); xstream.aliasField("TROUBLEMAKER", Ban.class, "person");xstream.aliasField("NAME1", Person.class, "firstName");xstream.aliasField("NAME2", Person.class, "lastName");xstream.aliasField("AGE", Person.class, "age"); // notice here that XML will be auto-converted to int "age"xstream.aliasField("NUMBER", Person.class, "documentNumber");/*Another way to define implicit collection*/ xstream.addImplicitCollection(Bans.class, "bans");Data data = (Data) xstream.fromXML(reader); // do the actual parsing// let's print results to check if data was parsedSystem.out.println("Number of bans = " + data.getBans().size());Ban firstBan = data.getBans().get(0);System.out.println("First ban = " + firstBan.toString());

如您所見,XStream可以輕松地將更復(fù)雜的XML結(jié)構(gòu)轉(zhuǎn)換為Java對(duì)象,如果XML不能滿足我們的需求,它還可以通過(guò)使用不同的名稱來(lái)調(diào)整結(jié)果。 但是有一件事情應(yīng)該引起您的注意:我們正在將表示Date的XML轉(zhuǎn)換為原始String,這與我們想要的結(jié)果不完全相同。 這就是為什么我們將添加轉(zhuǎn)換器來(lái)為我們做一些工作的原因。

使用現(xiàn)有的自定義類型轉(zhuǎn)換器

XStream庫(kù)附帶了一組針對(duì)大多數(shù)常見用例的內(nèi)置轉(zhuǎn)換器。 我們將使用DateConverter。 所以現(xiàn)在我們班的班級(jí)看起來(lái)像這樣:

public class Ban {private Date dateOfUpdate;private Person person; }

要使用DateConverter,我們只需將其注冊(cè)為我們期望出現(xiàn)在XML數(shù)據(jù)中的日期格式即可:

xstream.registerConverter(new DateConverter("yyyy-MM-dd", new String[] {}));

就是這樣。 現(xiàn)在,我們的對(duì)象不是String,而是使用Date實(shí)例填充的。 酷又容易! 但是,現(xiàn)有轉(zhuǎn)換器未涵蓋的類和情況又如何呢? 我們可以自己寫。

從頭開始編寫自定義轉(zhuǎn)換器

假設(shè)我們想知道幾天前完成更新,而不是dateOfUpdate:

public class Ban {private int daysAgo;private Person person; }

當(dāng)然,我們可以為每個(gè)Ban對(duì)象手動(dòng)計(jì)算它,但是使用可以為我們完成這項(xiàng)工作的轉(zhuǎn)換器看起來(lái)會(huì)更加有趣。 我們的DaysAgoConverter必須實(shí)現(xiàn)Converter接口,因此我們必須實(shí)現(xiàn)三種帶有簽名的方法,這些方法看起來(lái)有些嚇人:

public class DaysAgoConverter implements Converter {@Overridepublic void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {}@Overridepublic Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {}@Overridepublic boolean canConvert(Class type) {return false;} }

最后一個(gè)很容易,因?yàn)槲覀儗⒅晦D(zhuǎn)換Integer類。 但是,這些HierarchicalStreamWriter仍然剩下兩種方法,MarshallingContext,HierarchicalStreamReader和UnmarshallingContext參數(shù)。 幸運(yùn)的是,我們可以通過(guò)使用AbstractSingleValueConverter來(lái)避免與它們打交道,它使我們免受如此低級(jí)的機(jī)制的影響。 現(xiàn)在我們的班級(jí)看起來(lái)好多了:

public class DaysAgoConverter extends AbstractSingleValueConverter {@Overridepublic boolean canConvert(Class type) {return type.equals(Integer.class);}@Overridepublic Object fromString(String str) {return null;}public String toString(Object obj) {return null;} }

另外,我們必須重寫AbstractSingleValueConverter中定義的toString(Object obj)方法,因?yàn)槲覀円獙ate存儲(chǔ)在從Integer計(jì)算的XML中,而不是簡(jiǎn)單的Object.toString值,該值將從抽象父級(jí)中定義的默認(rèn)toString返回。

實(shí)作

下面的代碼非常簡(jiǎn)單,但是大多數(shù)有趣的行都被注釋了。 我跳過(guò)了所有驗(yàn)證內(nèi)容,以簡(jiǎn)化此示例。

public class DaysAgoConverter extends AbstractSingleValueConverter {private final static String FORMAT = "yyyy-MM-dd"; // default Date format that will be used in conversionprivate final DateTime now = DateTime.now().toDateMidnight().toDateTime(); // current day at midnightpublic boolean canConvert(Class type) {return type.equals(Integer.class); // Converter works only with Integers}@Overridepublic Object fromString(String str) {SimpleDateFormat format = new SimpleDateFormat(FORMAT);try {Date date = format.parse(str);return Days.daysBetween(new DateTime(date), now).getDays(); // we simply calculate days between using JodaTime} catch (ParseException e) {throw new RuntimeException("Invalid date format in " + str);}}public String toString(Object obj) {if (obj == null) {return null;}Integer daysAgo = ((Integer) obj);return now.minusDays(daysAgo).toString(FORMAT); // here we subtract days from now and return formatted date string} }

用法

要將自定義轉(zhuǎn)換器用于特定字段,我們必須使用registerLocalConverter通知它XStream對(duì)象:

xstream.registerLocalConverter(Ban.class, "daysAgo", new DaysAgoConverter());

我們使用“本地”方法將此轉(zhuǎn)換僅應(yīng)用于特定字段,而不應(yīng)用于XML文件中的每個(gè)Integer字段。 然后,我們將使用天數(shù)而不是日期填充Ban對(duì)象。

摘要

這就是我想在這篇文章中向您展示的全部?jī)?nèi)容。 現(xiàn)在,您已掌握有關(guān)XStream的功能以及如何將其輕松地將XML數(shù)據(jù)映射到Java對(duì)象的基本知識(shí)。如果您需要更高級(jí)的內(nèi)容,請(qǐng)查看項(xiàng)目官方頁(yè)面,因?yàn)樗浅:玫奈臋n和示例。

參考: XStream –來(lái)自Code Hard Go Pro博客的JCG合作伙伴 Tomasz Dziurko的XStreamely 簡(jiǎn)單方法,可使用Java處理XML數(shù)據(jù) 。

翻譯自: https://www.javacodegeeks.com/2013/04/xstream-xstreamely-easy-way-to-work-with-xml-data-in-java.html

總結(jié)

以上是生活随笔為你收集整理的XStream – XStreamely使用Java中的XML数据的简便方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。