XML文档操作之JAXP下实现
JAXP是java API for xml PRocessing的缩写。
其API可以在javax.xml.parsers 这个包中找到。这个包向用户提供了两个最重要的工厂类,SAXParserFactory 和DocumentBuilderFactory,我们可以通过这两个类实现之后对XML文件的操作。作为一个xml的解析器,w3c组织官方推荐使用Dom(Document Object Model 文档对象模型)方式进行解析,但是实际上的社区标准是SAX(Simple API For XML)。两者各有各的好处,下面是简易的两点区别:
- dom方式可以实现对XML文档的CRUD(即增删改查操作)
- sax主要是能够快速的查找某一个节点的值(注意不能CRUD)
今天我们就一起来看一看Dom方式来解析XML吧。
原理
DOM是一个以“面向对象”思路进行操作的方式,所谓对象就是指Dom实际上是将一个xml文件一下子装载到JVM中,然后根据XML文件的格式和内容在JAXP中创建一个“对象树”模型的方式,然后只需要针对这些对象进行操作就可以实现对XML文档的操作。
怎样得到一个对象模型:
- 利用DocumentBuilderFactory创建一个解析工厂实例(工厂)
- 得到一个DocumentBuilder解析器(机器)
- 然后通过对机器装载xml文件得到一个解析对象Document的实例
- 对这个Document进行一些列的操作即可
private static Document getDocument(String filePath) {
// TODO Auto-generated method stub
//get the prase factory
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
//get the prase machine
DocumentBuilder builder;
Document document = null;
try {
builder = factory.newDocumentBuilder();
//get the Object of the xml.file
document = builder.parse(filePath);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return document;
}
完成了对xml文档的操作之后,这就完了吗?思考发现并没有完成,因为我们操作的文档上之前一下子加载到内存中的文件,我们改变的仍旧只是内存中的文件,要想对原文件进行彻底的修改,我们还得有一些写回的操作,这就需要用到TransformerFactory类和Transformer类。
- 使用TransformerFactory工厂类得到一个工厂
- 通过工厂“加工”出来一个Transformer类
- 调用Transformer的transform方法就可以完成写回的操作了。
但是通过查询API文档,发现transform方法的参数需要进行一些包装。
所以还需要下面的包装方法。
public static void WriteBack(Document document,String path){
TransformerFactory factory= TransformerFactory.newInstance();
try {
Transformer transformer= (Transformer) factory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result= new StreamResult(new File("src/Person.xml"));
transformer.transform(source, result);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
剩下的操作就是比较简单的了,代码中注释也比较详尽,就不在过多的描述。
小结:
好处:全面,操控范围广
缺点:文件一下子装载到内存中,有可能导致内存泄漏(1、虽然Windows下有虚拟内存解决方案;2、我们也可以手动的更改Java虚拟机中-Xxm (大小)方式更改运行时内存;但最好是对文件较小的时候采用这个方式)
下面是我的项目中src目录下的一个Person.xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Persons>
<Person>
<Name>Summer</Name>
<Age>20</Age>
<Address>ShangHai</Address>
</Person>
<Person>
<Name>GRB</Name>
<Age>10</Age>
<Address>DaLian</Address>
</Person>
</Persons>
下面是对这个XML文档的CRUD操作:
package com.summer.jaxp;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class PraseXMLByJAXP {
public static void main(String[] args) {
// TODO Auto-generated method stub
//set the xml file path
String filePath="src/Person.xml";
//get the operation object ----document
Document document= getDocument(filePath);
//get the xml file result
getTheResult(document);
//update the xml file
upDateTheXMLFile(document);
//add one Node
addOneNode(document,filePath);
//delete one node
deleteOneNode(document , filePath , "Address");
//operate the attribute
operateTheAttribute(document,filePath);
}
private static void operateTheAttribute(Document document, String filePath) {
// TODO Auto-generated method stub
Element person = (Element) document.getElementsByTagName("Person").item(1);
//add some attribute
person.setAttribute("sex", "Man");
person.setAttribute("married", "Yes");
//update one special attribute
person.setAttribute("sex", "Woman");
//delete one special attribute
person.removeAttribute("sex");
//remember to write the operation result back to xml file, or that's only be saved in memary
WriteBack(document, filePath);
}
private static void deleteOneNode(Document document, String filePath,
String TagName) {
//you must get the node's parent then operate its's father to remove this node
Node oldChild = document.getElementsByTagName(TagName).item(1);
oldChild.getParentNode().removeChild(oldChild);
WriteBack(document, filePath);
}
private static void addOneNode(Document document,String filePath) {
// TODO Auto-generated method stub
Node parent = document.getElementsByTagName("Person").item(1);
Node child= document.createElement("Hobby");
child.setTextContent("Basketball and Coding!");
parent.appendChild(child);
WriteBack(document, filePath);
}
private static Document getDocument(String filePath) {
// TODO Auto-generated method stub
//get the prase factory
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
//get the prase machine
DocumentBuilder builder;
Document document = null;
try {
builder = factory.newDocumentBuilder();
//get the Object of the xml.file
document = builder.parse(filePath);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return document;
}
/**
* write the operation result back to xml file
* @param document
* @param path
*/
@Test
public static void WriteBack(Document document,String path){
TransformerFactory factory= TransformerFactory.newInstance();
try {
Transformer transformer= (Transformer) factory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result= new StreamResult(new File("src/Person.xml"));
transformer.transform(source, result);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void upDateTheXMLFile(Document document) {
// TODO Auto-generated method stub
NodeList list=document.getElementsByTagName("Name");
for(int i=1;i<list.getLength();i++){
Node node= list.item(i);
node.setTextContent("GRB");
}
WriteBack(document, "src/Person.xml");
}
private static void getTheResult(Document document) {
// TODO Auto-generated method stub
NodeList list=document.getElementsByTagName("Name");
for(int i=0;i<list.getLength();i++){
System.out.println(list.item(i).getTextContent());
}
}
}
代码运行后的Person.xml有很多已经改变,下面是总的操作的结果:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Persons>
<Person>
<Name>Summer</Name>
<Age>20</Age>
<Address>ShangHai</Address>
</Person>
<Person married="Yes">
<Name>GRB</Name>
<Age>10</Age>
<Hobby>Basketball and Coding!</Hobby>
</Person>
</Persons>
分析:
细心地朋友会发现:
- 第二个Person节点的属性多了一个
- 第二个Person节点的子节点address少了一个
- 第二个Person节点多了一个子节点hobby
这便是对XML文档操作的最好的体现。
总结:
使用解析器对xml的解析虽然方式众多,但是在实际中不同的情况选取合适的方式能大大减少不必要的麻烦。所以我们要谨慎的考虑到底要使用那种方式。
XML文档操作之JAXP下实现的更多相关文章
- XML文档操作集锦(C#篇)
在JSON没流行起来的时候xml一直作为程序存储配置信息的主流介质:特别是小型数据表方面还是不错的选择,所以经常涉及到的操作无非也就是增删改查,这篇博客主要是对这些对比较常用的操作做了个简单的总结 文 ...
- 关于XML文档操作类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...
- xml文档操作
/** * */package com.gootrip.util; import java.io.ByteArrayOutputStream;import java.io.File;import ja ...
- 用ORM的思想操作XML文档,一个对象就搞定不要太简单。滚蛋吧!XmlDocument、XmlNode、Xml***……
大家有没有这样的感受,一涉及XML文档操作就得百度一遍.是不是非!常!烦!.各种类型,各种方法,更别提为了找到一个节点多费劲.本来想写个XML操作的工具方法,写了两行一想既然XML文档是有规律的,如果 ...
- XPath操作XML文档
NET框架下的Sytem.Xml.XPath命名空间提供了一系列的类,允许应用XPath数据模式查询和展示XML文档数据. 3.1XPath介绍 主要的目的是在xml1.0和1.1文档节点树种定位节点 ...
- C#XmlHelper帮助类操作Xml文档的通用方法汇总
前言 该篇文章主要总结的是自己平时工作中使用频率比较高的Xml文档操作的一些常用方法和收集网上写的比较好的一些通用Xml文档操作的方法(主要包括Xml序列化和反序列化,Xml文件读取,Xml文档节点内 ...
- dom4j解析xml文档全面介绍
一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...
- dom4j 间隔插入节点 处理复杂的xml文档
前几周跟着老师做了一个小项目,个人主要负责xml文档处理,处理过程还是比较复杂的.此外这篇文章并不是讲基本的dom4j读写xml文档, 所以阅读此文的前提是你已经有了dom4j或jdom等处理xml文 ...
- XMLHelper类 源码(XML文档帮助类,静态方法,实现对XML文档的创建,及节点和属性的增、删、改、查)
以下是代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...
随机推荐
- MySQL使用判断
1.case语法 在第一个方案的返回结果中, value=compare-value.而第二个方案的返回结果是第一种情况的真实结果.如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE ...
- 【转】动态规划DP
[数据结构与算法] DP 动态规划 介绍 原创 2017年02月13日 00:42:51 最近在看算法导论. DP全称是dynamic programming,这里programming不是编程,是一 ...
- ubuntu 英文系统下安装中文输入法
环境:ubuntu15.10 64位 英文版 软件:fcitx输入法框架,及多种拼音输入法 linux的英文系统会比中文少很多麻烦,特别是在命令行输入路径的时候,如果路径是中文将是一件很头疼的问题.但 ...
- 使用 Nexus Repository Manager 搭建私有docker仓库
使用容器安装Nexus3 1.下载nexus3的镜像: docker pull sonatype/nexus3 2.使用镜像启动一个容器: docker run -d --name nexus -- ...
- Zookeeper Api
如何使用 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储 ...
- 实例演示如何在spring4.2.2中集成hibernate5.0.2并创建sessionFactory
本文地址:http://blog.csdn.net/sushengmiyan/article/details/49388209 文章作者:苏生米沿 本文目的:使用spring4.2.2集成hibern ...
- 豌豆夹Redis解决方案Codis源码剖析:Proxy代理
豌豆夹Redis解决方案Codis源码剖析:Proxy代理 1.预备知识 1.1 Codis Codis就不详细说了,摘抄一下GitHub上的一些项目描述: Codis is a proxy base ...
- JVM三种垃圾收集算法思想及发展过程
JVM垃圾收集算法的具体实现有很多种,本文只是介绍实现这些垃圾收集算法的三种思想和发展过程.所有的垃圾收集算法的具体实现都是遵循这三种算法思想而实现的. 1.标记-清除算法 标记-清除(Mark-Sw ...
- 从源码安装git
蛋疼的阿里云,git版本居然才1.9.只能手动安装了. 预装 apt-get update apt-get --yes install libcurl4-gnutls-dev libexpat1-de ...
- vbs注册表增删改
vbs注册表增删改非常简单.过去竟然能忍受那么多次手动在注册表编辑器操作...应该认真反思自己的懒惰了. Dim op Set op=WScript.CreateObject("WScrip ...