有的时候我们需要对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。

salesforce 零基础学习(三十二)通过Streams和DOM方式读写XML的更多相关文章

  1. salesforce零基础学习(一百二十)快去迁移你的代码中的 Alert / Confirm 以及 Prompt吧

    本篇参考: https://developer.salesforce.com/blogs/2022/01/preparing-your-components-for-the-removal-of-al ...

  2. salesforce零基础学习(九十二)使用Ant Migration Tool 实现Metadata迁移

    我们在做项目时经常会使用changeset作为部署工具,但是某些场景使用changeset会比较难操作,比如当我们在sandbox将apex class更改名字想要部署到生产的org或者其他环境的or ...

  3. salesforce 零基础学习(十八)WorkFlow介绍及用法

    说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配置workflow来完成以上 ...

  4. salesforce 零基础学习(十六)Validation Rules & Date/time

    上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...

  5. salesforce 零基础学习(十九)Permission sets 讲解及设置

    Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...

  6. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  7. salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见

    项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随 ...

  8. salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现

    项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...

  9. salesforce 零基础学习(六十八)http callout test class写法

    此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...

随机推荐

  1. oracle 中start with 的用法

    在重新开发已经有过的一个项目时,参考原本的sql,在一个存储过程中有用到 start with connect by,从网络找到下面资料. Oracle 提供了start with connect b ...

  2. listener监听器

    前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和 ...

  3. angular JS 做分页

    在网上找了一天,连一个像样点的分页DEMO都没找到,晕死了.大部分都是相互抄,有各种各样的问题,要不是代码有BUG,要不就是解释不明,GITHUB上下载下来的总是乱糟糟的.心累.

  4. 浅谈城市规划在移动GIS方面的应用发展

    1.概述 城市建设进程加快,城市规划管理工作日趋繁重,各种来源的数据产生各种层出不穷的问题,严重影响城市规划时的准确性,为此全面合理的掌握好各方面的城市规划资料才能做出更加科学的决策.移动端的兴起为规 ...

  5. 【DP】组合数字

    Password Attacker 题意就是给 M 个关键字,组合成 N 字符长度的结果,每一个关键字都必须在 N 位的字符中出现,有多少种可能结果. 范围 1 ≤ M ≤ N ≤ 100. 举例假设 ...

  6. windows8 APP开发的远程调试

    Win8上面的App开发远程调试: 这里先简单介绍一下对于win8的app的远程调试,环境设置:开发机器装有vs2012的win8系统,目标机器为虚拟机,预装win8系统. 1. 在虚拟机上安装vis ...

  7. 版本控制--github相关

    安装 Git 后,你应该做一些只需做一次的事情:系统设置——这样的设置在每台电脑上只需做一次: $ git config --global user.name "Your Name" ...

  8. poj 1737 Connected Graph

    // poj 1737 Connected Graph // // 题目大意: // // 带标号的连通分量计数 // // 解题思路: // // 设f(n)为连通图的数量,g(n)为非连通图的数量 ...

  9. “设计之变”--从iPhone应用到iPad应用

    在做APP的iPad版本设计时,我们常常需要考虑:如何在延续iPhone版本设计特色和优点同时,充分利用iPad的特性更好地进行设计.本文从iPad和iPhone的差异性入手,试图总结这一设计过程中需 ...

  10. 利用html5 canvas实现纯前端上传图片的裁剪

    今天跟大家分享一个前端裁剪图片的方法.许多网站都有设置用户头像的功能,用户可以选择一张本地的图片,然后用网站的裁剪工具进行裁剪,然后设置大小,位置合适的头像.当然,网上也有一些用js写的诸如此类裁剪的 ...