有的时候我们需要对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. Ubuntu16.04下面配置java环境变量

    我在ubuntu 16.04下面配置java环境变量的时候,开始在网上查信息的时候,没太注意ubuntu的版本,结果在.bashrc下面设置,在.profile下面设置,都不成功, 后面才想起来搜索u ...

  2. 如何使用yum下载rpm包

    一.使用 yum-downloadonly 插件 参考文章:ghosTzone 的博客http://ghostm55.is-programmer.com/posts/6422.html yum是一个优 ...

  3. SQL Server简洁查询正在运行的进程SQL

    通常我们可以使用 sp_who2 我们希望更加简洁的信息,下面这个查询使用系统表sys.sysprocesses,以及sys.dm_exec_sql_text做OUTER APPLY. T-SQL是这 ...

  4. berkeley db 内存池 LRU算法

    priority based lru in src/mp/mp_fget.c, __memp_fget(), 初始化 一个page buffer时, 设置其 priority: bhp->pri ...

  5. 结对开发训练(郭林林&胡潇丹)

    此次编程题为:求一个整数数组最大子数组之和,要求时间复杂度为O(n). 首先,我们对题目做出分析,做出第一种预行方案,即定义一个数组,当数组中元素大于等于0时,进行累加:若小于0,则与后面的数作比较, ...

  6. JavaWeb的学习之Servlet(转载自孤傲苍狼)

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  7. DLL和LIB的一些知识点(网上搜集)

    关于lib和dll的区别如下:(1)lib是编译时用到的,dll是运行时用到的.如果要完成源代码的编译,只需要lib:如果要使动态链接的程序运行起来,只需要dll.(2)如果有dll文件,那么lib一 ...

  8. iptables Data filtering详解

    内容简介防火墙的概述iptables简介iptables基础iptables语法iptables实例案例详解(一)防火墙的简介防火墙是指设置在不同网络或网络安全域之间的一系列部件的组合,它能增强机构内 ...

  9. 使用WMI和性能计数器监控远程服务器权限设置

    应用场景:在web服务器中,通过.NET编码使用WMI查询远程服务器的一些硬件配置信息,使用性能计数器查询远程机器的运行时资源使用情况.在网上没有找到相关的东西,特记录与大家共享. 将web服务器和所 ...

  10. Github教程(0)

    Git下载:https://git-for-windows.github.io/ 我下载的版本是:Git-2.6.3-64-bit.exe 安装:略 默认选项点击"下一步"即可 安 ...