Java中对XML的解析详解
先简单说下前三种方式:
dom方式:个人理解类似.net的xmldocument,解析的时候效率不高,占用内存,不适合大xml的解析;
sax方式:基于事件的解析,当解析到xml的某个部分的时候,会触发特定事件,可以在自定义的解析类中定义当事件触发时要做得事情;个人感觉一种很另类的方式,不知道.net体系下是否有没有类似的方式?
stax方式:个人理解类似.net的xmlreader方式,效率高,占用内存少,适用大xml的解析;
不过sax方式之前也用过,本文主要介绍jaxb,这里只贴下主要代码:
import java.util.arraylist;
import java.util.list;
import org.xml.sax.attributes;
import org.xml.sax.saxexception;
import org.xml.sax.helpers.defaulthandler;
public class configparser extends defaulthandler {
private string currentconfigsection;
public sysconfigitem sysconfig;
public list<interfaceconfigitem> interfaceconfiglist;
public list<ftpconfigitem> ftpconfiglist;
public list<adapterconfigitem> adapterconfiglist;
public void startdocument() throws saxexception {
sysconfig = new sysconfigitem();
interfaceconfiglist = new arraylist<interfaceconfigitem>();
ftpconfiglist = new arraylist<ftpconfigitem>();
adapterconfiglist = new arraylist<adapterconfigitem>();
}
public void enddocument() throws saxexception {
}
public void startelement(string uri, string localname, string qname, attributes attributes) throws saxexception {
if (qname.equalsignorecase("item") && attributes.getlength() > 0) {
if (currentconfigsection.equalsignorecase("sysconfigitem")) {
sysconfig = new sysconfigitem(attributes);
} else if (currentconfigsection.equalsignorecase("interfaceconfigitems")) {
interfaceconfiglist.add(new interfaceconfigitem(attributes));
} else if (currentconfigsection.equalsignorecase("ftpconfigitems")) {
ftpconfiglist.add(new ftpconfigitem(attributes));
} else if (currentconfigsection.equalsignorecase("adapterconfigitems")) {
adapterconfiglist.add(new adapterconfigitem(attributes));
}
} else {
currentconfigsection = qname;
}
}
public void endelement(string uri, string localname, string qname) throws saxexception {
}
public void characters(char ch[], int start, int length) throws saxexception {
}
}
import java.lang.reflect.field;
import java.text.dateformat;
import java.text.parseexception;
import java.text.simpledateformat;
import java.util.date;
import org.xml.sax.attributes;
public class configitembase {
private static dateformat dateformat = new simpledateformat("yyyy-mm-dd hh:mm:ss");
public configitembase() {
}
/**
* 目前只支持几种常用类型 如果需要支持其他类型,请修改这里的代码
*
* @param attributes
*/
public configitembase(attributes attributes) {
class<?> cls = this.getclass();
field[] fields = cls.getdeclaredfields();
for (field field : fields) {
string fieldtype = field.gettype().getsimplename();
for (int i = 0; i < attributes.getlength(); i++) {
if (attributes.getqname(i).equalsignorecase(field.getname())) {
field.setaccessible(true);
try {
if (fieldtype.equalsignorecase("string")) {
field.set(this, attributes.getvalue(attributes.getqname(i)));
} else if (fieldtype.equalsignorecase("integer")) {
field.set(this, integer.valueof(attributes.getvalue(attributes.getqname(i))));
} else if (fieldtype.equalsignorecase("double")) {
field.set(this, double.valueof(attributes.getvalue(attributes.getqname(i))));
} else if (fieldtype.equalsignorecase("date")) {
field.set(this, getdate(attributes.getvalue(attributes.getqname(i))));
} else {
system.out.println("warning:unhandler field(" + field.getname() + "-" + fieldtype + ")");
}
} catch (illegalargumentexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
}
break;
}
}
}
}
public string tostring() {
string result = "";
class<?> cls = this.getclass();
string classnamestring = cls.getname();
result += classnamestring.substring(classnamestring.lastindexof('.') + 1, classnamestring.length()) + ":";
field[] fields = cls.getdeclaredfields();
for (field field : fields) {
try {
result += field.getname() + "=" + field.get(this) + ";";
} catch (illegalargumentexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
}
}
return result;
}
/**
* 处理时间类型属性(时间格式要求为:yyyy-mm-dd hh:mm:ss)
*
* @param datestring
* @return
*/
private static date getdate(string datestring) {
date date = null;
try {
date = dateformat.parse(datestring);
} catch (parseexception e) {
e.printstacktrace();
}
return date;
}
}
下面重点介绍一下最方便的:jaxb(java architecture for xml binding)
这里用比较复杂的移动batchsyncorderrelationreq接口xml做为示例(感觉能解这个大家基本上够用了),报文格式如下(svccont里的cdata内容是报文体,太恶心了):
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<interboss>
<version>0100</version>
<testflag>0</testflag>
<biptype>
<bipcode>bip2b518</bipcode>
<activitycode>t2101518</activitycode>
<actioncode>0</actioncode>
</biptype>
<routinginfo>
<origdomain>boss</origdomain>
<routetype>routetype</routetype>
<routing>
<homedomain>xxxx</homedomain>
<routevalue>routevalue</routevalue>
</routing>
</routinginfo>
<transinfo>
<sessionid>2013041017222313925676</sessionid>
<transido>2013041017222313925676</transido>
<transidotime>20130410172223</transidotime>
<transidh></transidh>
<transidhtime></transidhtime>
</transinfo>
<snreserve>
<transidc></transidc>
<convid></convid>
<cutoffday></cutoffday>
<osntime></osntime>
<osnduns></osnduns>
<hsnduns></hsnduns>
<msgsender></msgsender>
<msgreceiver></msgreceiver>
<priority></priority>
<servicelevel></servicelevel>
<svcconttype></svcconttype>
</snreserve>
<response>
<rsptype>rsptype</rsptype>
<rspcode>rspcode</rspcode>
<rspdesc>rspdesc</rspdesc>
</response>
<svccont><![cdata[<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<batchsyncorderrelationreq>
<msgtransactionid>210001bip2b518130410172223651627</msgtransactionid>
<reqnum>2</reqnum>
<reqbody>
<oprnumb>210001bip2b518130410172224341871</oprnumb>
<subscriptioninfo>
<oprtime>oprtime1</oprtime>
<actionid>actionid1</actionid>
<brand>brand1</brand>
<efftime>efftime1</efftime>
<expiretime>expiretime1</expiretime>
<feeuser_id>feeuserid1</feeuser_id>
<destuser_id>destuserid1</destuser_id>
<actionreasonid>actionid1</actionreasonid>
<servtype>servtype1</servtype>
<subservtype>subservtype1</subservtype>
<spid>spid1</spid>
<spservid>spservid1</spservid>
<accessmode>accessmode1</accessmode>
<servparaminfo>
<para_num>0</para_num>
<para_info>
<para_name></para_name>
<para_value></para_value>
</para_info>
</servparaminfo>
<feetype>feetype1</feetype>
</subscriptioninfo>
</reqbody>
<reqbody>
<oprnumb>210001bip2b518130410172224420909</oprnumb>
<subscriptioninfo>
<oprtime>oprtime2</oprtime>
<actionid>actionid2</actionid>
<brand>brand2</brand>
<efftime>efftime2</efftime>
<expiretime>expiretime2</expiretime>
<feeuser_id>feeuserid2</feeuser_id>
<destuser_id>destuserid2</destuser_id>
<actionreasonid>actionid2</actionreasonid>
<servtype>servtype2</servtype>
<subservtype>subservtype2</subservtype>
<spid>spid2</spid>
<spservid>spservid2</spservid>
<accessmode>accessmode2</accessmode>
<servparaminfo>
<para_num>0</para_num>
<para_info>
<para_name></para_name>
<para_value></para_value>
</para_info>
</servparaminfo>
<feetype>feetype2</feetype>
</subscriptioninfo>
</reqbody>
</batchsyncorderrelationreq>]]></svccont>
</interboss>
解码代码如下:
@xmlrootelement(name = "batchsyncorderrelationreq")
@xmlaccessortype(xmlaccesstype.field)
public class batchsyncorderrelationreq extends bossmessage<batchsyncorderrelationreq> {
@xmlelement(name = "msgtransactionid")
private string msgtransactionid = "";
@xmlelement(name = "reqnum")
private string reqnum = "";
@xmlelement(name = "reqbody")
private list<batchsyncorderrelationreqbody> reqbodylist;
public batchsyncorderrelationreq() {
}
public string getmsgtransactionid() {
return this.msgtransactionid;
}
public void setmsgtransactionid(string msgtransactionid) {
this.msgtransactionid = msgtransactionid;
}
public string getreqnum() {
return this.reqnum;
}
public void setreqnum(string reqnum) {
this.reqnum = reqnum;
}
public list<batchsyncorderrelationreqbody> getreqbodylist() {
return this.reqbodylist;
}
public void setreqbodylist(list<batchsyncorderrelationreqbody> reqbodylist) {
this.reqbodylist = reqbodylist;
}
@override
public batchsyncorderrelationreq deserialized(string interbossxmlcontent) throws businessexception {
try {
// deserialized for head
jaxbcontext jaxbcxt4head = jaxbcontext.newinstance(messagehead.class);
unmarshaller unmarshaller4head = jaxbcxt4head.createunmarshaller();
messagehead head = (messagehead) unmarshaller4head.unmarshal(new stringreader(interbossxmlcontent));
// deserialized for syncorderrelationreq body
jaxbcontext jaxbcxt4body = jaxbcontext.newinstance(batchsyncorderrelationreq.class);
unmarshaller unmarshaller4body = jaxbcxt4body.createunmarshaller();
batchsyncorderrelationreq batchsyncorderrelationreq = (batchsyncorderrelationreq) unmarshaller4body.unmarshal(new stringreader(head.getsvccont().trim()));
batchsyncorderrelationreq.sethead(head);
return batchsyncorderrelationreq;
} catch (jaxbexception e) {
throw new businessexception("syncorderrelationreq.deserialized() error!(" + interbossxmlcontent + ")", e);
}
}
}
@xmlaccessortype(xmlaccesstype.field)
public class batchsyncorderrelationreqbody {
@xmlelement(name = "oprnumb")
private string oprnumb = "";
@xmlelement(name = "subscriptioninfo")
private subscriptioninfo subscriptioninfo;
public batchsyncorderrelationreqbody(){
}
public batchsyncorderrelationreqbody(string oprnumb, subscriptioninfo subscriptioninfo) {
this.oprnumb = oprnumb;
this.subscriptioninfo = subscriptioninfo;
}
public string getoprnumb() {
return this.oprnumb;
}
public void setoprnumb(string oprnumb) {
this.oprnumb = oprnumb;
}
public subscriptioninfo getsubscriptioninfo() {
return this.subscriptioninfo;
}
public void setsubscriptioninfo(subscriptioninfo subscriptioninfo) {
this.subscriptioninfo = subscriptioninfo;
}
}
@xmlaccessortype(xmlaccesstype.field)
public class subscriptioninfo {
@xmlelement(name = "oprtime")
private string oprtime = "";
@xmlelement(name = "actionid")
private string actionid = "";
@xmlelement(name = "brand")
private string brand = "";
@xmlelement(name = "efftime")
private string efftime = "";
@xmlelement(name = "expiretime")
private string expiretime = "";
@xmlelement(name = "feeuser_id")
private string feeuserid = "";
@xmlelement(name = "destuser_id")
private string destuserid = "";
@xmlelement(name = "actionreasonid")
private string actionreasonid = "";
@xmlelement(name = "servtype")
private string servtype = "";
@xmlelement(name = "subservtype")
private string subservtype = "";
@xmlelement(name = "spid")
private string spid = "";
@xmlelement(name = "spservid")
private string spservid = "";
@xmlelement(name = "accessmode")
private string accessmode = "";
@xmlelement(name = "feetype")
private string feetype = "";
public subscriptioninfo() {
}
public subscriptioninfo(
string oprtime,
string actionid,
string brand,
string efftime,
string expiretime,
string feeuserid,
string destuserid,
string actionreasonid,
string servtype,
string subservtype,
string spid,
string spservid,
string accessmode,
string feetype) {
this.oprtime = oprtime;
this.actionid = actionid;
this.brand = brand;
this.efftime = efftime;
this.expiretime = expiretime;
this.feeuserid = feeuserid;
this.destuserid = destuserid;
this.actionreasonid = actionreasonid;
this.servtype = servtype;
this.subservtype = subservtype;
this.spid = spid;
this.spservid = spservid;
this.accessmode = accessmode;
this.feetype = feetype;
}
public string getoprtime() {
return this.oprtime;
}
public void setoprtime(string oprtime) {
this.oprtime = oprtime;
}
public string getactionid() {
return this.actionid;
}
public void setactionid(string actionid) {
this.actionid = actionid;
}
public string getbrand() {
return this.brand;
}
public void setbrand(string brand) {
this.brand = brand;
}
public string getefftime() {
return this.efftime;
}
public void setefftime(string efftime) {
this.efftime = efftime;
}
public string getexpiretime() {
return this.expiretime;
}
public void setexpiretime(string expiretime) {
this.expiretime = expiretime;
}
public string getfeeuserid() {
return this.feeuserid;
}
public void setfeeuserid(string feeuserid) {
this.feeuserid = feeuserid;
}
public string getdestuserid() {
return this.destuserid;
}
public void setdestuserid(string destuserid) {
this.destuserid = destuserid;
}
public string getactionreasonid() {
return this.actionreasonid;
}
public void setactionreasonid(string actionreasonid) {
this.actionreasonid = actionreasonid;
}
public string getservtype() {
return this.servtype;
}
public void setservtype(string servtype) {
this.servtype = servtype;
}
public string getsubservtype() {
return this.subservtype;
}
public void setsubservtype(string subservtype) {
this.subservtype = subservtype;
}
public string getspid() {
return this.spid;
}
public void setspid(string spid) {
this.spid = spid;
}
public string getspservid() {
return this.spservid;
}
public void setspservid(string spservid) {
this.spservid = spservid;
}
public string getaccessmode() {
return this.accessmode;
}
public void setaccessmode(string accessmode) {
this.accessmode = accessmode;
}
public string getfeetype() {
return this.feetype;
}
public void setfeetype(string feetype) {
this.feetype = feetype;
}
}