目前我知道的JAVA解析XML的方式有:DOM, SAX, StAX;如果选用这几种,感觉还是有点麻烦;如果使用:JAXB(Java Architecture for XML Binding),个人觉得太方便了!
先简单说下前三种方式:
DOM方式:个人理解类似.net的XmlDocument,解析的时候效率不高,占用内存,不适合大XML的解析;
SAX方式:基于事件的解析,当解析到xml的某个部分的时候,会触发特定事件,可以在自定义的解析类中定义当事件触发时要做得事情;个人感觉一种很另类的方式,不知道.Net体系下是否有没有类似的方式?
StAX方式:个人理解类似.net的XmlReader方式,效率高,占用内存少,适用大XML的解析;
不过SAX方式之前也用过,本文主要介绍JAXB,这里只贴下主要代码:
1 import java.util.ArrayList; 2 import java.util.List; 3 4 import org.xml.sax.Attributes; 5 import org.xml.sax.SAXException; 6 import org.xml.sax.helpers.DefaultHandler; 7 8 public class ConfigParser extends DefaultHandler { 9 private String currentConfigSection; 10 11 public SysConfigItem sysConfig; 12 public List<InterfaceConfigItem> interfaceConfigList; 13 public List<FtpConfigItem> ftpConfigList; 14 public List<AdapterConfigItem> adapterConfigList; 15 16 public void startDocument() throws SAXException { 17 sysConfig = new SysConfigItem(); 18 interfaceConfigList = new ArrayList<InterfaceConfigItem>(); 19 ftpConfigList = new ArrayList<FtpConfigItem>(); 20 adapterConfigList = new ArrayList<AdapterConfigItem>(); 21 } 22 23 public void endDocument() throws SAXException { 24 25 } 26 27 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 28 if (qName.equalsIgnoreCase("Item") && attributes.getLength() > 0) { 29 if (currentConfigSection.equalsIgnoreCase("SysConfigItem")) { 30 sysConfig = new SysConfigItem(attributes); 31 } else if (currentConfigSection.equalsIgnoreCase("InterfaceConfigItems")) { 32 interfaceConfigList.add(new InterfaceConfigItem(attributes)); 33 } else if (currentConfigSection.equalsIgnoreCase("FtpConfigItems")) { 34 ftpConfigList.add(new FtpConfigItem(attributes)); 35 } else if (currentConfigSection.equalsIgnoreCase("AdapterConfigItems")) { 36 adapterConfigList.add(new AdapterConfigItem(attributes)); 37 } 38 } else { 39 currentConfigSection = qName; 40 } 41 } 42 43 public void endElement(String uri, String localName, String qName) throws SAXException { 44 45 } 46 47 public void characters(char ch[], int start, int length) throws SAXException { 48 49 } 50 }
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>
解码代码如下:
1 @XmlRootElement(name = "batchSyncOrderRelationReq") 2 @XmlAccessorType(XmlAccessType.FIELD) 3 public class BatchSyncOrderRelationReq extends BossMessage<BatchSyncOrderRelationReq> { 4 5 @XmlElement(name = "msgTransactionID") 6 private String msgTransactionId = ""; 7 8 @XmlElement(name = "reqNum") 9 private String reqNum = ""; 10 11 @XmlElement(name = "reqBody") 12 private List<BatchSyncOrderRelationReqBody> reqBodyList; 13 14 public BatchSyncOrderRelationReq() { 15 16 } 17 18 public String getMsgTransactionId() { 19 return this.msgTransactionId; 20 } 21 22 public void setMsgTransactionId(String msgTransactionId) { 23 this.msgTransactionId = msgTransactionId; 24 } 25 26 public String getReqNum() { 27 return this.reqNum; 28 } 29 30 public void setReqNum(String reqNum) { 31 this.reqNum = reqNum; 32 } 33 34 public List<BatchSyncOrderRelationReqBody> getReqBodyList() { 35 return this.reqBodyList; 36 } 37 38 public void setReqBodyList(List<BatchSyncOrderRelationReqBody> reqBodyList) { 39 this.reqBodyList = reqBodyList; 40 } 41 131 @Override 132 public BatchSyncOrderRelationReq Deserialized(String interBossXmlContent) throws BusinessException { 133 try { 134 // deserialized for head 135 JAXBContext jaxbCxt4Head = JAXBContext.newInstance(MessageHead.class); 136 Unmarshaller unmarshaller4Head = jaxbCxt4Head.createUnmarshaller(); 137 MessageHead head = (MessageHead) unmarshaller4Head.unmarshal(new StringReader(interBossXmlContent)); 138 139 // deserialized for SyncOrderRelationReq body 140 JAXBContext jaxbCxt4Body = JAXBContext.newInstance(BatchSyncOrderRelationReq.class); 141 Unmarshaller unmarshaller4Body = jaxbCxt4Body.createUnmarshaller(); 142 BatchSyncOrderRelationReq batchSyncOrderRelationReq = (BatchSyncOrderRelationReq) unmarshaller4Body.unmarshal(new StringReader(head.getSvcCont().trim())); 143 batchSyncOrderRelationReq.setHead(head); 144 145 return batchSyncOrderRelationReq; 146 } catch (JAXBException e) { 147 throw new BusinessException("SyncOrderRelationReq.Deserialized() Error!(" + interBossXmlContent + ")", e); 148 } 149 } 150 151 }
@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; } }