jaxp使用笔记
XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论
DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML文档过大,会出现内存溢出的问题,DOM也有优点:方便进行增删改操作
SAX解析方式是根据事件驱动一行一行进行加载解析的,所以不会出现内存溢出的问题,而且方便查询,但是它有个缺点:不能进行增删改操作
目前XML的解析器有:
- sun开发的jaxp(本次记录的)
- dom4j (最为常用)
- jdom (使用较少)
注意:这里说的是解析器,解析器是根据解析技术开发的工具,解析技术记住DOM和SAX即可
因为jaxp是sun公司开发的,直接存在于JDK中,所以还是有必要学习一下
jaxp进行DOM解析
使用jaxp进行DOM解析可以分为四步:
第一步 创建解析器工厂
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
第二步 根据工厂创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
第三步 使用解析器解析XML文件,得到Document对象
Document document = builder.parse("XML文件");
第四步 根据jaxp的API对Document对象进行操作
例如 getElementsByTagName(标签名)获得节点集合 NodeList类的getLength()方法获得节点个数
NodeList类的item(int)方法获得某个节点 Node类的getTextContent()方法获得节点的文本值 等等
person.xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<person>
<student>
<name>lz</name>
<age>21</age>
</student>
<student>
<name>zhanshang</name>
<age>21</age>
</student>
</person>
先来看一个简单解析XML文件的例子(从name节点集合中获得每个name节点的文本值):
/**
* 使用jaxp的DOM解析方法解析XML
* @throws Exception
*/
@Test
public void fun1() throws Exception{
//1.创建工厂
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//2.根据工厂创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//3.解析XML得到Document对象
Document document = builder.parse("src/person.xml");
//4.根据Document对象得到元素集合
NodeList nodeList = document.getElementsByTagName("name");
//5.遍历节点集合,得到节点的值 使用item()方法根据下标获得节点
for (int i = 0; i < nodeList.getLength(); i++) {
String value=nodeList.item(i).getTextContent();
System.out.println(value);
}
}
注意:其中的Document和NodeList,Node等类都是org.w3c.dom包下的,不要导错
结果输出:
lz
zhanshang
添加节点
添加节点使用的是appChild()方法,和js中DOM操作的添加节点方法名是一样的,添加节点操作中第四步需要说明一下:我们需要创建节点(创建元素节点createElement()方法,创建文本节点 createTextNode()方法),然后把节点添加到父节点下,其实逻辑和js中DOM一致,然后我们需要回写到XML文件中,因为我们之前的操作都是在内存中,需要回写到XML文件
/**
* 添加节点
* @throws Exception
*/
@Test
public void fun2() throws Exception{
//1.创建解析器工厂
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//2.根据工厂创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//3.解析XML,得到Document
Document document = builder.parse("src/person.xml");
//得到第一个student结点,并添加结点(内存中)
Node student = document.getElementsByTagName("student").item(0);
Element sex = document.createElement("sex");
Text nan = document.createTextNode("男");
sex.appendChild(nan);
student.appendChild(sex);
//4.回写数据到XML文件中
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
注意:使用javax.xml.transform包下的Transformer类回写,这个类也是先创建工厂,然后根据工厂创建Transformer类,最后使用这个类的transform()方法。使用jaxp添加节点会使XML文件的格式变乱,因为添加节点之后不会格式化,使用dom4j就可以格式化XML文件
person.xml文件变为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
<student>
<name>lz</name>
<age>21</age>
<sex>男</sex>
</student>
<student>
<name>zhanshang</name>
<age>21</age>
</student>
</person>
修改操作
修改文本节点的值使用的是Node类的setTextContent()方法,和getTextContent()方法相对
/**
* 修改节点
* @throws Exception
*/
@Test
public void fun3() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
Node sex = document.getElementsByTagName("sex").item(0);
sex.setTextContent("nan");
//回写XML
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
person.xml文件变为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
<student>
<name>lz</name>
<age>21</age>
<sex>nan</sex>
</student>
<student>
<name>zhanshang</name>
<age>21</age>
</student>
</person>
删除节点
接下来我们就把sex这个节点给删除吧,使用的方法是Node类的removeChild(),注意:使用1添加和删除都是相对于操作的节点的父节点来说的,所以需要先找到其父节点
/**
* 删除节点
* @throws Exception
*/
@Test
public void fun4() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
Node student1 = document.getElementsByTagName("student").item(0);
Node sex1 = document.getElementsByTagName("sex").item(0);
student1.removeChild(sex1);
//回写XML
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
person.xml文件又变回:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
<student>
<name>lz</name>
<age>21</age>
</student>
<student>
<name>zhanshang</name>
<age>21</age>
</student>
</person>
注意:DOM的增删改操作都需要在最后回写到XML文件中,不然只是在内存中操作
遍历节点
我是想把所有的元素节点遍历出来,遍历节点使用的是Node类的getChildNodes()方法,但是这个方法遍历只可以遍历一层层级关系,所以需要递归调用
/**
* 遍历节点
* @throws Exception
*/
@Test
public void fun5() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
list1(document);
} private void list1(Node node){ //遍历节点 Node类是Document类的父类
if(node.getNodeType()==Node.ELEMENT_NODE){ //判断是否为元素节点 ELEMEN_NODE静态常量量 还有其他的静态常量表示其他类型的节点
System.out.println(node.getNodeName());
}
NodeList nodeList = node.getChildNodes();
for(int i=0;i<nodeList.getLength();i++){
list1(nodeList.item(i)); //递归调用
}
}
注意:list1()方法中有一个判断,判断该节点类型是否为元素节点,如果为元素节点才输出,如果不判断遍历之后会把空格,换行都当成文本节点输出,js的DOM操作中也有该问题
结果输出为 :
person
student
name
age
student
name
age
jaxp进行SAX解析
因为SAX解析不可以进行增删改操作,所以都是查询操作
步骤分为四步(大致上与DOM解析的步骤一致,只是使用的是继承DefaultHandler的类进行处理解析结果):
第一步 得到解析器工厂
SAXParserFactory factory=SAXParserFactory.newInstance();
第二步 根据工厂得到解析器
SAXParser parser = factory.newSAXParser();
第三步 解析XML文件,使用继承于DefaultHandler的类进行处理
parser.parse("src/person.xml", new MyHandler1());
MyHandler类继承DefaultHandler类,这个父类,最主要的方法是 :
startElement() 处理开始标签,
endElement() 处理结束标签,
characters() 处理文本
前两者都有一个String类型的变量表示该标签名
获得所有的标签
/**
* 获取所有标签
*
*/
@Test
public void fun1() throws Exception{
//1.得到解析器工厂
SAXParserFactory factory=SAXParserFactory.newInstance();
//2.根据工厂创建解析器
SAXParser parser = factory.newSAXParser();
//3.解析XML文件
parser.parse("src/person.xml", new MyHandler1());
} class MyHandler1 extends DefaultHandler{ @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("<"+qName+">"); //这里没有使用println,因为解析XML会把空格和换行都解析出来
} @Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("</"+qName+">");
} @Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.print(new String(ch,start,length));
} }
结果输出为:
<person>
<student>
<name>lz</name>
<age>21</age>
</student>
<student>
<name>zhanshang</name>
<age>20</age>
</student>
</person>
获得标签的值
/**
* 获得所有name标签的值
*/
@Test
public void fun2()throws Exception{
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse("src/person.xml", new MyHandler2());
} class MyHandler2 extends DefaultHandler{ private boolean flag=false; //设置一个标志位,解析到name标签时改变标志位 @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equals("name")){
flag=true;
}
} @Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equals("name")){
flag=false;
}
} @Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(flag==true){
System.out.println(new String(ch,start,length));
}
} }
结果输出为:
lz
zhanshang
得到某一个标签的值
/**
* 获得第二个name标签的值
*/
@Test
public void fun3()throws Exception{
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse("src/person.xml", new MyHandler3());
} class MyHandler3 extends DefaultHandler{ private boolean flag=false; private int index=1; @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equals("name")){
flag=true;
}
} @Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equals("name")){
flag=false;
index++;
}
} @Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(flag==true&&index==2){
System.out.println(new String(ch,start,length));
}
} }
结果输出为:
zhanshang
jaxp使用笔记的更多相关文章
- Javaweb学习笔记——(六)——————xml中jaxp两种解析方式和dom4j运用
1.xml的scheam约束 dtd的语法:<!ElEMENT 元素名称 约束> **schema符合xml的语法,xml语句 **一个xml中可以有多个schema,多个schema使用 ...
- 超全面的JavaWeb笔记day05<xml&dtd&jaxp>
0.表单提交方式(*****) button提交 超链接提交 事件 1.xml简介和应用(了解) 2.xml文档声明和乱码解决(*****) 文档声明 必须放在第一行第一列 设置xml编码和保存编码一 ...
- Android笔记——Android中数据的存储方式(二)
我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效 ...
- spring 入门笔记(一)
最近学习spring 通过笔记形式加深自己对spring的理解,也希望能跟各位入门者分享和讨论. 一.下载spring 下载spring也费了不少功夫,目前还没从spring官网找到下载入口,我从下面 ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
- day0203 XML 学习笔记
day02, 03 1. xml语言和作用 2. xml语法详解 2.1 xml 语法声明 2.1.1 encoding 属性 2.1.2 standalone 属性 2.2 xml 元素(Eleme ...
- JAVA与DOM解析器提高(DOM/SAX/JDOM/DOM4j/XPath) 学习笔记二
要求 必备知识 JAVA基础知识.XML基础知识. 开发环境 MyEclipse10 资料下载 源码下载 sax.dom是两种对xml文档进行解析的方法(没有具体实现,只是接口),所以只有它们是无 ...
- XML解析之JAXP
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- Digester学习笔记(一)转载
本博文系转载,作者原文已经无法找到,感谢原作者的辛苦整理 Digester学习笔记(一) 在windows下开发程序,用M$提供的接口处理.ini文件或管理注册表的键值是非常方便的.在java平台上开 ...
随机推荐
- iOS 阶段学习第六天笔记(数组)
iOS学习( ...
- mac 使用 pf 做端口转发
Mac os中我发现直接输入localhost是拒绝访问的,原因在于OSX 对于1024内端口需要 root 权限,因此需要做一个80端口的转发. 曾经的 ipfw 已经被 pf 所替换. 首先我们要 ...
- 每周荐书:Kotlin、分布式、Keras(评论送书)
每周荐书:Kotlin.分布式.Keras(评论送书) 感谢大家对每周荐书栏目的支持,先公布下上周中奖名单 法式三文鱼 名优秀评论可以免费获得此书. Kotlin实战 首著席卷而来 Android ...
- keras 报错 ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("embedding_1/random_uniform:0", shape=(5001, 128), dtype=float32)'
在服务器上训练并保存模型,复制到本地之后load_model()报错: ValueError: Tensor conversion requested dtype int32 for Tensor w ...
- OkHttp使用Get和Post访问服务器的工具类(一)
首先来简单介绍一下okttp框架,类似于HttpUrlConnection,Android6.0以后,废弃了Apache Http Client,只有HttpUrlConnection和OkHttp了 ...
- js之简易计算器
<!DOCTYPE html PUBLIC "-//W3C//Dli XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 求整数A和B的二进制表示中有多少位是不同?
如果有题目要求整数A和B二进制表示中多少位是不同的? 那我们要先考虑一个unsigned类型中变量1的个数?我们可以考虑简单的移位运算,向右移位,我们进行判断如果不是1直接丢掉,使用&运算符即 ...
- matlab图像处理注意溢出!先要im2double!
imagedata_comb=imagedata_ebic*addnumber_ebic+imagedata_sem*addnumber_sem; %注意溢出啊!!!uint8最大值是255,也就是说 ...
- docker学习(一)在centos7上安装与启动docker
CentOS Docker 安装 1.Docker支持以下的CentOS版本: CentOS 7 (64-bit) CentOS 6.5 (64-bit) 或更高的版本 前提条件 目前,CentOS ...
- BZOJ2946 Poi2000 公共串 【后缀自动机】
Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果 Input 文件的第一行是整数 n,1<=n& ...