Android利用Dom对XML进行增删改查操作详解

1. 概述

平常我们一般是使用JSON与服务器做数据通信,JSON的话,直接用GSON或者其他库去解析很简单。但是,其他有些服务器会返回XML格式的文件,这时候就需要去读取XML文件了。

XML的解析有三种方式,在Android中提供了三种解析XML的方式:DOM(Document Objrect Model) , SAX(Simple API XML) ,以及Android推荐的Pull解析方式,他们也各有弊端,而这里来看看使用DOM的方式。

2. Dom解析

DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。再形象点,就是一棵树,多节点的树,称为Dom树。

Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应节点对象(Node的子类对象),以便于调用其特有的方法。

Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容.

3. Dom解析代码示例

代码如下:

/**
 * DOM解析
 * 把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
 * 缺点是消耗大量的内存。
 * @param xmlFilePath 文件
 * @return Document
 */
public static Document loadWithDom(String xmlFilePath) {
 try {
 File file = new File(xmlFilePath);
 if (!file.exists()) {
 throw new RuntimeException("not find file:" + xmlFilePath);
 }
 else {
 InputStream inputStream = new FileInputStream(file);
 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
 Document document = documentBuilder.parse(inputStream);
 try {
 inputStream.close();
 } catch (Exception e) {
 e.printStackTrace();
 }
 return document;
 }
 } catch (ParserConfigurationException | IOException | SAXException e) {
 return null;
 }
 }

上面的方法是同步的,最终返回的是一个 Document 对象。

4. 查找

自定义一个稍微简单的XML:

<?xml version="1.0" encoding="utf-8" standalone='yes'?>
<packages key1="value1" key2="value2">
 <last-platform-version internal="22" external="22" fingerprint="honeybot/H1f/H1f:5.1.1/LMY47V/huiyu01091530:userdebug/test-keys"/>
 <database-version internal="3" external="3"/>
 <permission-trees/>
 <permissions>
 <item name="android.permission.SET_SCREEN_COMPATIBILITY" package="android" protection="2"/>
 <item name="android.permission.MEDIA_CONTENT_CONTROL" package="android" protection="18"/>
 <item name="android.permission.DELETE_PACKAGES" package="android" protection="18"/>
 <item name="com.android.voicemail.permission.ADD_VOICEMAIL" package="android" protection="1"/>
 </permissions>
 <package name="com.android.providers.downloads" codePath="/system/priv-app/DownloadProvider" nativeLibraryPath="/system/priv-app/DownloadProvider/lib" flags="1074282053" ft="15f9e785498" it="15f9e785498" ut="15f9e785498" version="22" sharedUserId="10002">
 <sigs count="1">
 <cert index="1"/>
 </sigs>
 <proper-signing-keyset identifier="2"/>
 <signing-keyset identifier="2"/>
 </package>
</packages>

使用上面的代码去解析,Document如下:

Documnet,it is the root of the document tree, and provides the primary access to the document's data. 就是整个xml的root,通过它可以获取到xml的相关信息。

xmlVersion,代表的是xml的版本

children,子节点,是Element,对应上面的,是最外层的package

Element,是xml的最外层的结点,由document.getDocumentElement() 得到 。

Node,结点。何为结点?其实就是一个<abc></abc>的一个结点信息,存储着一些,结点本身的属性,和其结点下的子结点等等。

//得到最外层的节点
Element element = document.getDocumentElement();
//得到节点的属性
NamedNodeMap namedNodeMap = element.getAttributes();
//便利属性并log输出
for (int i = 0; i < namedNodeMap.getLength(); i++) {
 Node node = namedNodeMap.item(i);
 node.getNodeName();//key
 node.getTextContent();//value
 node.getNodeType();//node type
}
//得到子节点列表
NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
 Node node = nodeList.item(i);
 //每个node下面,也可能有node,和,node的属性,获取都如上所示
}

Node,每个node里面的属性,也是node,每个node下的子节点node也是一个一个node

 //节点的属性
 Node node = namedNodeMap.item(i);
 node.getNodeName();//key
 node.getTextContent();//value
 node.getNodeType();//node type
 //节点下的子节点
 NodeList nodeList = element.getChildNodes();
 for (int i = 0; i < nodeList.getLength(); i++) {
 Node node = nodeList.item(i);
 //每个node下面,也可能有node,和,node的属性,获取都如上所示
 }

4.1 实践一下,查找

在android系统里面,安装的每一个app,其信息都被存到一个xml里面:/data/system/packages.xml,可以通过root去查看里面的内容,大概如下(其实上面的例子就是从这个xml文件copy来的):

<?xml version="1.0" encoding="utf-8" standalone='yes'?>
<packages key1="value1" key2="value2">
 <last-platform-version internal="22" external="22" fingerprint="honeybot/H1f/H1f:5.1.1/LMY47V/huiyu01091530:userdebug/test-keys"/>
 <database-version internal="3" external="3"/>
 <permission-trees/>
 <permissions>
 //一堆的权限
 <item name="android.permission.SET_SCREEN_COMPATIBILITY" package="android" protection="2"/>
 </permissions>
 //一堆的app
 <package name="com.android.providers.downloads" codePath="/system/priv-app/DownloadProvider" nativeLibraryPath="/system/priv-app/DownloadProvider/lib" flags="1074282053" ft="15f9e785498" it="15f9e785498" ut="15f9e785498" version="22" sharedUserId="10002">
 <sigs count="1">
 <cert index="1"/>
 </sigs>
 <proper-signing-keyset identifier="2"/>
 <signing-keyset identifier="2"/>
 </package>
</packages>

而现在有个需求,查找是否有app:com.xx.xx,也就是查找xml中的package节点中的name属性值有没有此包名。
我们先封装一下代码吧:

public class XmlUtils {
 /**
 * DOM解析
 * 把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
 * 缺点是消耗大量的内存。
 * @param xmlFilePath 文件
 * @return Document
 */
 public static Document loadWithDom(String xmlFilePath) {
 try {
 File file = new File(xmlFilePath);
 if (!file.exists()) {
 throw new RuntimeException("not find file:" + xmlFilePath);
 }
 else {
 InputStream inputStream = new FileInputStream(file);
 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
 Document document = documentBuilder.parse(inputStream);
 try {
  inputStream.close();
 } catch (Exception e) {
  e.printStackTrace();
 }
 return document;
 }
 } catch (ParserConfigurationException | IOException | SAXException e) {
 return null;
 }
 }
 public static Observable<Document> loadWithDomRx(String xmlFilePath) {
 return Observable.just(loadWithDom(xmlFilePath));
 }
}

封装好之后,就可以写代码,如下:

//加载文件
XmlUtils.loadWithDomRx("/sdcard/Test.xml")
 .subscribe(document -> {
 //判断是否加载到文件
 if (document!=null && document.getDocumentElement()!=null) {
 //判断有无node
 NodeList nodeList = document.getDocumentElement().getChildNodes();
 if (nodeList != null) {
  //遍历node list
  for (int i = 0; i < nodeList.getLength(); i++) {
  Node node = nodeList.item(i);
  //判断是否是package节点
  if (node.getNodeName() != null && node.getNodeName().equals("package")) {
  //提取参数列表
  NamedNodeMap namedNodeMap = node.getAttributes();
  if (namedNodeMap != null && namedNodeMap.getLength()>0) {
  //判断参数中是否有com.xx.xx
  Node n = namedNodeMap.item(0);
  if (n.getNodeName()!=null && n.getNodeName().equals("name")) {
   if (n.getTextContent()!=null && n.getTextContent().equals("com.xx.xx")) {
   //进行您的操作
   }
  }
  }
  }
  }
 }
 }
 });

注意,要做好判空。有可能很多node不存在参数,或者没有子节点。

5. 增删改

当加载xml到内存中后,你可以对document进行修改

增加

Element element = document.createElement("New Node");
element.setAttribute("key1","value1");
element.setAttribute("key2","value2");
node.appendChild(element);

删除

//注意的是,你需要先找出这个node对象,因为api没有提供直接remove index 的node的方法。
element.removeChild(node);
node1.removeChild(node2);

修改

//找到具体的node,或者,elemnet,修改:
node.setNodeValue("edit key");
node.setTextContent("edit value");

6. 保存

在内存中修改好的document对象,直接保存为新的xml文件,代码如下:

/**
 * 保存修改后的Doc
 * http://blog.csdn.net/franksun1991/article/details/41869521
 * @param doc doc
 * @param saveXmlFilePath 路径
 * @return 是否成功
 */
public static boolean saveXmlWithDom(Document doc,String saveXmlFilePath) {
 if (doc==null || saveXmlFilePath==null || saveXmlFilePath.isEmpty())
 return false;
 try {
 //将内存中的Dom保存到文件
 TransformerFactory tFactory = TransformerFactory.newInstance();
 Transformer transformer = tFactory.newTransformer();
 //设置输出的xml的格式,utf-8
 transformer.setOutputProperty("encoding", "utf-8");
 transformer.setOutputProperty("version",doc.getXmlVersion());
 DOMSource source = new DOMSource(doc);
 //打开输出流
 File file = new File(saveXmlFilePath);
 if (!file.exists())
 Log.i("XmlUtils","saveXmlWithDom,createNewFile:"+file.createNewFile());
 OutputStream outputStream = new FileOutputStream(file);
 //xml的存放位置
 StreamResult src = new StreamResult(outputStream);
 transformer.transform(source, src);
 return true;
 } catch (Exception e) {
 e.printStackTrace();
 return false;
 }
}

7. 附上工具类

/**
 * <pre>
 * author: Chestnut
 * blog : http://www.jianshu.com/u/a0206b5f4526
 * time : 2018/1/10 17:14
 * desc : XML解析工具类
 * thanks To:
 * 1. [Android解析XML的三种方式] http://blog.csdn.net/d_shadow/article/details/55253586
 * 2. [Android几种解析XML方式的比较] http://blog.csdn.net/isee361820238/article/details/52371342
 * 3. [android xml 解析 修改] http://blog.csdn.net/i_lovefish/article/details/39476051
 * 4. [android 对xml文件的pull解析,生成xml ,对xml文件的增删] http://blog.csdn.net/jamsm/article/details/52205800
 * dependent on:
 * update log:
 * </pre>
 */
public class XmlUtils {
 /**
 * DOM解析
 * 把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
 * 缺点是消耗大量的内存。
 * @param xmlFilePath 文件
 * @return Document
 */
 public static Document loadWithDom(String xmlFilePath) {
 try {
 File file = new File(xmlFilePath);
 if (!file.exists()) {
 throw new RuntimeException("not find file:" + xmlFilePath);
 }
 else {
 InputStream inputStream = new FileInputStream(file);
 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
 Document document = documentBuilder.parse(inputStream);
 try {
  inputStream.close();
 } catch (Exception e) {
  e.printStackTrace();
 }
 return document;
 }
 } catch (ParserConfigurationException | IOException | SAXException e) {
 return null;
 }
 }
 public static Observable<Document> loadWithDomRx(String xmlFilePath) {
 return Observable.just(loadWithDom(xmlFilePath));
 }
 /**
 * 保存修改后的Doc
 * http://blog.csdn.net/franksun1991/article/details/41869521
 * @param doc doc
 * @param saveXmlFilePath 路径
 * @return 是否成功
 */
 public static boolean saveXmlWithDom(Document doc,String saveXmlFilePath) {
 if (doc==null || saveXmlFilePath==null || saveXmlFilePath.isEmpty())
 return false;
 try {
 //将内存中的Dom保存到文件
 TransformerFactory tFactory = TransformerFactory.newInstance();
 Transformer transformer = tFactory.newTransformer();
 //设置输出的xml的格式,utf-8
 transformer.setOutputProperty("encoding", "utf-8");
 transformer.setOutputProperty("version",doc.getXmlVersion());
 DOMSource source = new DOMSource(doc);
 //打开输出流
 File file = new File(saveXmlFilePath);
 if (!file.exists())
 Log.i("XmlUtils","saveXmlWithDom,createNewFile:"+file.createNewFile());
 OutputStream outputStream = new FileOutputStream(file);
 //xml的存放位置
 StreamResult src = new StreamResult(outputStream);
 transformer.transform(source, src);
 return true;
 } catch (Exception e) {
 e.printStackTrace();
 return false;
 }
 }
 public static Observable<Boolean> saveXmlWithDomRx(Document doc,String saveXmlFilePath) {
 return Observable.just(saveXmlWithDom(doc, saveXmlFilePath));
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

您可能感兴趣的文章:

  • Android开发之DOM解析xml文件的方法
  • Android编程解析XML方法详解(SAX,DOM与PULL)
  • Android应用中使用DOM方式解析XML格式数据的基本方法
  • Android解析XML的三种方式SAX、Pull、Dom
  • Android创建与解析XML(二)——详解Dom方式
  • Android 创建与解析XML(五)——详解Dom4j方式
  • 详解Android之解析XML文件三种方式(DOM,PULL,SAX)
  • Android利用SAX对XML进行增删改查操作详解
(0)

相关推荐

  • Android利用SAX对XML进行增删改查操作详解

    前言 解析XML的方式有很多种,大家比较熟悉的可能就是DOM解析. DOM(文件对象模型)解析:解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以根据DOM接口来操作这个树结构了. 优点:整个文档读入内存,方便操作:支持修改.删除和重现排列等多种功能. 缺点:将整个文档读入内存中,保留了过多的不需要的节点,浪费内存和空间. 使用场合:一旦读入文档,还需要多次对文档进行操作,并且在硬件资源充足的情况下(内存,CPU). 为了解决DOM解析存在的问题,就出现了SAX解析.其特点为: 优

  • Android 创建与解析XML(五)——详解Dom4j方式

    1.Dom4j概述 dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX and JAXP. dom4j官方网址:dom4j dom4j源码下载:dom4j download 本示例中,需要导入dom4j

  • 详解Android之解析XML文件三种方式(DOM,PULL,SAX)

    1.xml文件代码 <?xml version="1.0" encoding="UTF-8" ?> <%@ page language="java" contentType="text/xml; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core

  • Android应用中使用DOM方式解析XML格式数据的基本方法

    DOM比SAX更容易掌握,因为她没有涉及回调和复杂的状态管理,然而,DOM的实现常常将所有的XML节点保存在内存中,这样使的处理较大的文档效率低. XML基本的节点类型 node - DOM基本的数据类型 Element - 最主要处理的对象是Element Attr - 元素的属性 Text - 一个Element 或者Attr的实际内容 Document - 代表整个XML文档,一个Document对象通常也称为一颗DOM树   1.在src目录下新建一个android.xml <?xml

  • Android编程解析XML方法详解(SAX,DOM与PULL)

    本文实例讲述了Android编程解析XML方法.分享给大家供大家参考,具体如下: XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能.今天就由我向大家介绍一下在Android平台下几种常见的XML解析和创建的方法. 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析器,下面,我将一一向大家详细介绍. SAX解析器: SAX(Simple API for XML)解析器是一种基于事

  • Android解析XML的三种方式SAX、Pull、Dom

    在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),本文对android解析xml的这三种方式进行一次总结. 今天解析的xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8"?> <channel> <item id=&quo

  • Android开发之DOM解析xml文件的方法

    本文实例讲述了Android中DOM解析xml文件的方法.分享给大家供大家参考,具体如下: 一.在assets文件中写xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>李明</name> <age>30</age> </person> <pe

  • Android创建与解析XML(二)——详解Dom方式

    1. Dom概述 Dom方式创建XML,应用了标准xml构造器 javax.xml.parsers.DocumentBuilder 来创建 XML 文档,需要导入以下内容 javax.xml.parsers javax.xml.parsers.DocumentBuilder javax.xml.parsers.DocumentBuilderFactory javax.xml.parsers.ParserConfigurationException; javax.xml.transform jav

  • Android利用Dom对XML进行增删改查操作详解

    1. 概述 平常我们一般是使用JSON与服务器做数据通信,JSON的话,直接用GSON或者其他库去解析很简单.但是,其他有些服务器会返回XML格式的文件,这时候就需要去读取XML文件了. XML的解析有三种方式,在Android中提供了三种解析XML的方式:DOM(Document Objrect Model) , SAX(Simple API XML) ,以及Android推荐的Pull解析方式,他们也各有弊端,而这里来看看使用DOM的方式. 2. Dom解析 DOM解析器在解析XML文档时,

  • java中JDBC增删改查操作详解

    目录 前言 一.增删改操作 1.1 PreparedStatement介绍  1.2 增删改操作   1.3 测试 二.查操作 2.1 通用对不同表进行一条数据查询操作 2.2 通用对不同表进行多条数据查询操作 总结 前言         在上一篇博客我们介绍了JDBC的概念以及连接数据库的五种方式JDBC概述及数据库连接方式(数据库连接方式推荐使用第五种),那么我们既然连接上数据库了,那就要对数据进行操作了,那么这一篇我们就来介绍常规的增删改 查操作.       我们先看一遍步骤:    

  • MySQL筑基篇之增删改查操作详解

    目录 一.增加表中数据 1.无自增列时 2.有自增列时 二.删除表中数据 1.使用delete 2.使用truncate 三.修改表中数据 四.*查询操作 1.简单查询 2.条件查询 3.排序 一.增加表中数据 1.无自增列时 1.指定字段添加数据 给表中的部分列添加数据:值的顺序必须跟指定列的顺序保持一致 语法:insert into 表名(列1,列2,...) values(值1,值2,...) 2.默认添加数据 向表中的所有列添加数据:值的顺序必须跟字段顺序保持一致 语法:insert i

  • Python实现连接MySql数据库及增删改查操作详解

    本文实例讲述了Python实现连接MySql数据库及增删改查操作.分享给大家供大家参考,具体如下: 在本文中介绍 Python3 使用PyMySQL连接数据库,并实现简单的增删改查.(注意是python3) 1.安装PyMySQL PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb.PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库.在使用 PyMySQ

  • python3.6连接mysql数据库及增删改查操作详解

    折腾好半天的数据库连接,由于之前未安装 pip ,而且自己用的python 版本为3.6. 只能用 pymysql 来连接数据库,下边 简单介绍一下 连接的过程,以及简单的增删改查操作. 1.通过 pip 安装 pymysql 进入 cmd  输入  pip install pymysql   回车等待安装完成: 安装完成后出现如图相关信息,表示安装成功. 2.测试连接 import pymysql #导入 pymysql 如果编译未出错,即表示 pymysql 安装成功 简单的增删改查操作 示

  • express+mongoose实现对mongodb增删改查操作详解

    本文实例讲述了express+mongoose实现对mongodb增删改查操作.分享给大家供大家参考,具体如下: 项目地址:https://github.com/jrainlau/mongoose_crud 写在开头 本文主要分享我如何使用express+mongoose对mongodb实现增删改查操作,感谢cnode社区所有精品文章的帮助,以及@airuikun的开源项目airuikun/mongoose_crud对我的启发. 学习nodejs已经小半个月了,一直琢磨着做一些什么东西出来.由于

  • AJAX实现数据的增删改查操作详解【java后台】

    本文实例讲述了AJAX实现数据的增删改查操作.分享给大家供大家参考,具体如下: 主页:index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></sc

  • Java对XML文件增删改查操作示例

    本文实例讲述了Java对XML文件增删改查操作.分享给大家供大家参考,具体如下: xml文件: <?xml version="1.0" encoding="UTF-8"?> <books> <book> <name>哈里波特</name> <price>10</price> <memo>这是一本很好看的书.</memo> </book> <b

  • PHP实现对xml的增删改查操作案例分析

    本文实例讲述了PHP实现对xml的增删改查操作.分享给大家供大家参考,具体如下: 案例: index.php <?php header("content-type:text/html;charset=utf-8"); $xmldom = new DOMDocument(); $xmldom->load("demo2.xml"); //查询学生信息 $stus = $xmldom->getElementsByTagName("学生"

随机推荐