有的時候我們需要對XML進行讀寫操作,常用的XML操作主要有Streams和DOM方式。
一.Streams方式
Streams常用到的類主要有兩個XmlStreamReader 以及XmlStreamWriter。
XmlStreamReader:此種讀取方式的讀的特點為從上而下讀,下圖是根據reader的EventType自上而下的運行步驟。

我們將此xml讀取后封裝到一個Goods的List中,Goods包括item,name以及type屬性,代碼如下:
/* * 假定目前XML數據樣式為: *<?xml version="1.0"?> *<goodsList> * <goods item="1"> * <name>華為手機</name> * <type>華為</type> * </goods> * <goods item="2"> * <name>小米手機</name> * <type>小米</type> * </goods> *</goodsList> * 需要將xml解析成Goods的一個List */ public class XmlReaderController { public class Goods { public String item{get;set;} public String name{get;set;} public String type{get;set;} } public List<Goods> getGoodsListByXmlFile(String goodsXml) { XmlStreamReader reader = new XmlStreamReader(goodsXml); Boolean flagXmlEnd = true; List<Goods> goodsList = new List<Goods>(); while(flagXmlEnd) { Goods tempGoods; if(reader.getEventType() == XmlTag.START_ELEMENT) { if(reader.getLocalName().equalsIgnoreCase('goods')) { tempGoods = getGoods(reader); } } if(reader.hasNext()) { reader.next(); } else { flagXmlEnd = false; break; } if(tempGoods != null) { goodsList.add(tempGoods); } } return goodsList; } Goods getGoods(XmlStreamReader reader) { Goods tempGoods = new Goods(); tempGoods.item = reader.getAttributeValue(null,'item'); Boolean flagIsLoop = true; while(flagIsLoop) { if(reader.hasNext()) { reader.next(); if(reader.getEventType() == XmlTag.START_ELEMENT) { if(reader.getLocalName().equalsIgnoreCase('name')) { reader.next(); tempGoods.name = reader.getText(); } else if(reader.getLocalName().equalsIgnoreCase('type')) { reader.next(); tempGoods.type = reader.getText(); } } if(reader.getEventType() == XmlTag.END_ELEMENT && reader.getLocalName().equalsIgnoreCase('goods')) { flagIsLoop = false; break; } } else { flagIsLoop = false; break; } } return tempGoods; } }
在匿名塊測試方法:
String goodsXml = '<?xml version="1.0"?>' +
'<goodsList>' +
'<goods item="1">' +
'<name>華為手機</name>' +
'<type>華為</type>' +
'</goods>' +
'<goods item="2">' +
'<name>小米手機</name>' +
'<type>小米</type>' +
'</goods>' +
'</goodsList>';
List<XmlReaderController.Goods> goodsList = new XmlReaderController().getGoodsListByXmlFile(goodsXml);
System.debug(JSON.serialize(goodsList));
顯示結果:
[
{
"type":"華為",
"name":"華為手機",
"item":"1"
},
{
"type":"小米",
"name":"小米手機",
"item":"2"
}
XmlStreamWriter:處理過程同XmlStreamReader,需要從上到下進行寫入,例如如果寫出上述的xml文件,需要先startDocument,然后再startElement.....要注意每個start需要對應相應的end方法。
public class XmlWriterController { public static void writeXml() { XmlStreamWriter writer = new XmlStreamWriter(); writer.writeStartDocument('utf-8','1.0'); writer.writeComment('goodsList start here'); writer.writeStartElement('','goodsList','http://www.goods.com'); writer.writeNamespace('', 'http://www.goods.com'); writer.writeStartElement(null,'goods',null); writer.writeAttribute(null,null,'item','1'); writer.writeStartElement(null,'name',null); writer.writeCharacters('華為手機'); writer.writeEndElement(); writer.writeStartElement(null,'type',null); writer.writeCharacters('華為'); writer.writeEndElement(); writer.writeEndElement(); writer.writeStartElement(null,'goods',null); writer.writeAttribute(null,null,'item','2'); writer.writeStartElement(null,'name',null); writer.writeCharacters('小米手機'); writer.writeEndElement(); writer.writeStartElement(null,'type',null); writer.writeCharacters('小米'); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndDocument(); system.debug(writer.getXmlString()); } }
二.Dom解析

dom解析原理同java對於dom解析相同,這里,goodsList作為根節點,goodsList的子節點有goods1,goods.他們分別有屬性item1和item2,goods1以及goods2又分別有相應的子節點。
通過dom方式將上述xml解析成Goods的List。
public class DomXmlController { public class Goods { String item{get;set;} String name{get;set;} String type{get;set;} } public List<Goods> getGoodsViaXmlDom(String xmlString) { Dom.Document document = new Dom.Document(); document.load(xmlString); Dom.XmlNode rootElement = document.getRootElement(); List<Goods> goodsList = new List<Goods>(); for(Dom.XmlNode node : rootElement.getChildElements()) { if(node.getName().equalsIgnoreCase('goods')) { Goods tempGoods = new Goods(); tempGoods = getGoodsNameAndType(node); tempGoods.item = node.getAttribute('item',null); goodsList.add(tempGoods); } } return goodsList; } Goods getGoodsNameAndType(Dom.XmlNode parentNode) { transient Goods tempGoods = new Goods(); for(Dom.XmlNode node : parentNode.getChildElements()) { if(node.getName().equalsIgnoreCase('name')) { tempGoods.name = node.getText(); } else if(node.getName().equalsIgnoreCase('type')) { tempGoods.type = node.getText(); } } return tempGoods; } }
匿名塊測試內容如下:
String goodsXml = '<?xml version="1.0"?>' +
'<goodsList>' +
'<goods item="1">' +
'<name>華為手機</name>' +
'<type>華為</type>' +
'</goods>' +
'<goods item="2">' +
'<name>小米手機</name>' +
'<type>小米</type>' +
'</goods>' +
'</goodsList>';
System.debug(JSON.serialize(new DomXmlController().getGoodsViaXmlDom(goodsXml)));
顯示結果:

總結:apex對於xml操作和java很類似,或者說大部分都是從java過來的,如果java解析xml很嫻熟情況下,使用apex解析xml只需要看看方法就OK了。本篇只是描述最簡單的xml操作,篇中好多方法沒有使用到,有興趣的或者想深入的可以自己看一下相關的api。
