XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论

DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML文档过大,会出现内存溢出的问题,DOM也有优点:方便进行增删改操作

SAX解析方式是根据事件驱动一行一行进行加载解析的,所以不会出现内存溢出的问题,而且方便查询,但是它有个缺点:不能进行增删改操作

目前XML的解析器有:

  1. sun开发的jaxp(本次记录的)
  2. dom4j (最为常用)
  3. jdom (使用较少)

注意:这里说的是解析器,解析器是根据解析技术开发的工具,解析技术记住DOM和SAX即可

因为jaxp是sun公司开发的,直接存在于JDK中,所以还是有必要学习一下

jaxp进行DOM解析

使用jaxp进行DOM解析可以分为四步:

第一步 创建解析器工厂

  1. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();

第二步 根据工厂创建解析器

  1. DocumentBuilder builder = factory.newDocumentBuilder();

第三步 使用解析器解析XML文件,得到Document对象

  1. Document document = builder.parse("XML文件");

第四步 根据jaxp的API对Document对象进行操作

例如  getElementsByTagName(标签名)获得节点集合     NodeList类的getLength()方法获得节点个数

NodeList类的item(int)方法获得某个节点    Node类的getTextContent()方法获得节点的文本值 等等

person.xml文件:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <person>
  2. <student>
  3. <name>lz</name>
  4. <age>21</age>
  5. </student>
  6. <student>
  7. <name>zhanshang</name>
  8. <age>21</age>
  9. </student>
  10. </person>

先来看一个简单解析XML文件的例子(从name节点集合中获得每个name节点的文本值):

  1. /**
  2. * 使用jaxp的DOM解析方法解析XML
  3. * @throws Exception
  4. */
  5. @Test
  6. public void fun1() throws Exception{
  7. //1.创建工厂
  8. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  9. //2.根据工厂创建解析器
  10. DocumentBuilder builder = factory.newDocumentBuilder();
  11. //3.解析XML得到Document对象
  12. Document document = builder.parse("src/person.xml");
  13. //4.根据Document对象得到元素集合
  14. NodeList nodeList = document.getElementsByTagName("name");
  15. //5.遍历节点集合,得到节点的值 使用item()方法根据下标获得节点
  16. for (int i = 0; i < nodeList.getLength(); i++) {
  17. String value=nodeList.item(i).getTextContent();
  18. System.out.println(value);
  19. }
  20. }

注意:其中的Document和NodeList,Node等类都是org.w3c.dom包下的,不要导错

结果输出:

  1. lz
  2. zhanshang

添加节点

添加节点使用的是appChild()方法,和js中DOM操作的添加节点方法名是一样的,添加节点操作中第四步需要说明一下:我们需要创建节点(创建元素节点createElement()方法,创建文本节点 createTextNode()方法),然后把节点添加到父节点下,其实逻辑和js中DOM一致,然后我们需要回写到XML文件中,因为我们之前的操作都是在内存中,需要回写到XML文件

  1. /**
  2. * 添加节点
  3. * @throws Exception
  4. */
  5. @Test
  6. public void fun2() throws Exception{
  7. //1.创建解析器工厂
  8. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  9. //2.根据工厂创建解析器
  10. DocumentBuilder builder = factory.newDocumentBuilder();
  11. //3.解析XML,得到Document
  12. Document document = builder.parse("src/person.xml");
  13. //得到第一个student结点,并添加结点(内存中)
  14. Node student = document.getElementsByTagName("student").item(0);
  15. Element sex = document.createElement("sex");
  16. Text nan = document.createTextNode("男");
  17. sex.appendChild(nan);
  18. student.appendChild(sex);
  19. //4.回写数据到XML文件中
  20. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  21. Transformer transformer = transformerFactory.newTransformer();
  22. transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
  23. }

注意:使用javax.xml.transform包下的Transformer类回写,这个类也是先创建工厂,然后根据工厂创建Transformer类,最后使用这个类的transform()方法。使用jaxp添加节点会使XML文件的格式变乱,因为添加节点之后不会格式化,使用dom4j就可以格式化XML文件

person.xml文件变为:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
  2. <student>
  3. <name>lz</name>
  4. <age>21</age>
  5. <sex></sex>
  6. </student>
  7. <student>
  8. <name>zhanshang</name>
  9. <age>21</age>
  10. </student>
  11. </person>

修改操作

修改文本节点的值使用的是Node类的setTextContent()方法,和getTextContent()方法相对

  1. /**
  2. * 修改节点
  3. * @throws Exception
  4. */
  5. @Test
  6. public void fun3() throws Exception{
  7. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  8. DocumentBuilder builder = factory.newDocumentBuilder();
  9. Document document = builder.parse("src/person.xml");
  10. Node sex = document.getElementsByTagName("sex").item(0);
  11. sex.setTextContent("nan");
  12. //回写XML
  13. TransformerFactory transformerFactory=TransformerFactory.newInstance();
  14. Transformer transformer = transformerFactory.newTransformer();
  15. transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
  16. }

person.xml文件变为:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
  2. <student>
  3. <name>lz</name>
  4. <age>21</age>
  5. <sex>nan</sex>
    </student>
  6. <student>
  7. <name>zhanshang</name>
  8. <age>21</age>
  9. </student>
  10. </person>

删除节点

接下来我们就把sex这个节点给删除吧,使用的方法是Node类的removeChild(),注意:使用1添加和删除都是相对于操作的节点的父节点来说的,所以需要先找到其父节点

  1. /**
  2. * 删除节点
  3. * @throws Exception
  4. */
  5. @Test
  6. public void fun4() throws Exception{
  7. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  8. DocumentBuilder builder = factory.newDocumentBuilder();
  9. Document document = builder.parse("src/person.xml");
  10. Node student1 = document.getElementsByTagName("student").item(0);
  11. Node sex1 = document.getElementsByTagName("sex").item(0);
  12. student1.removeChild(sex1);
  13. //回写XML
  14. TransformerFactory transformerFactory=TransformerFactory.newInstance();
  15. Transformer transformer = transformerFactory.newTransformer();
  16. transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
  17. }

person.xml文件又变回:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
  2. <student>
  3. <name>lz</name>
  4. <age>21</age>
  5. </student>
  6. <student>
  7. <name>zhanshang</name>
  8. <age>21</age>
  9. </student>
  10. </person>

注意:DOM的增删改操作都需要在最后回写到XML文件中,不然只是在内存中操作

遍历节点

我是想把所有的元素节点遍历出来,遍历节点使用的是Node类的getChildNodes()方法,但是这个方法遍历只可以遍历一层层级关系,所以需要递归调用

  1. /**
  2. * 遍历节点
  3. * @throws Exception
  4. */
  5. @Test
  6. public void fun5() throws Exception{
  7. DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  8. DocumentBuilder builder = factory.newDocumentBuilder();
  9. Document document = builder.parse("src/person.xml");
  10. list1(document);
  11. }
  12.  
  13. private void list1(Node node){ //遍历节点 Node类是Document类的父类
  14. if(node.getNodeType()==Node.ELEMENT_NODE){ //判断是否为元素节点 ELEMEN_NODE静态常量量 还有其他的静态常量表示其他类型的节点
  15. System.out.println(node.getNodeName());
  16. }
  17. NodeList nodeList = node.getChildNodes();
  18. for(int i=0;i<nodeList.getLength();i++){
  19. list1(nodeList.item(i)); //递归调用
  20. }
  21. }

注意:list1()方法中有一个判断,判断该节点类型是否为元素节点,如果为元素节点才输出,如果不判断遍历之后会把空格,换行都当成文本节点输出,js的DOM操作中也有该问题

结果输出为 :

  1. person
  2. student
  3. name
  4. age
  5. student
  6. name
  7. age

jaxp进行SAX解析

因为SAX解析不可以进行增删改操作,所以都是查询操作

步骤分为四步(大致上与DOM解析的步骤一致,只是使用的是继承DefaultHandler的类进行处理解析结果):

第一步 得到解析器工厂

  1. SAXParserFactory factory=SAXParserFactory.newInstance();

第二步 根据工厂得到解析器

  1. SAXParser parser = factory.newSAXParser();

第三步 解析XML文件,使用继承于DefaultHandler的类进行处理

  1. parser.parse("src/person.xml", new MyHandler1());

MyHandler类继承DefaultHandler类,这个父类,最主要的方法是 :

startElement() 处理开始标签,

endElement() 处理结束标签,

characters() 处理文本

前两者都有一个String类型的变量表示该标签名

获得所有的标签

  1. /**
  2. * 获取所有标签
  3. *
  4. */
  5. @Test
  6. public void fun1() throws Exception{
  7. //1.得到解析器工厂
  8. SAXParserFactory factory=SAXParserFactory.newInstance();
  9. //2.根据工厂创建解析器
  10. SAXParser parser = factory.newSAXParser();
  11. //3.解析XML文件
  12. parser.parse("src/person.xml", new MyHandler1());
  13. }
  14.  
  15. class MyHandler1 extends DefaultHandler{
  16.  
  17. @Override
  18. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  19. System.out.print("<"+qName+">"); //这里没有使用println,因为解析XML会把空格和换行都解析出来
  20. }
  21.  
  22. @Override
  23. public void endElement(String uri, String localName, String qName) throws SAXException {
  24. System.out.print("</"+qName+">");
  25. }
  26.  
  27. @Override
  28. public void characters(char[] ch, int start, int length) throws SAXException {
  29. System.out.print(new String(ch,start,length));
  30. }
  31.  
  32. }

结果输出为:

  1. <person>
  2. <student>
  3. <name>lz</name>
  4. <age>21</age>
  5. </student>
  6. <student>
  7. <name>zhanshang</name>
  8. <age>20</age>
  9. </student>
  10. </person>

获得标签的值

  1. /**
  2. * 获得所有name标签的值
  3. */
  4. @Test
  5. public void fun2()throws Exception{
  6. SAXParserFactory factory=SAXParserFactory.newInstance();
  7. SAXParser parser = factory.newSAXParser();
  8. parser.parse("src/person.xml", new MyHandler2());
  9. }
  10.  
  11. class MyHandler2 extends DefaultHandler{
  12.  
  13. private boolean flag=false; //设置一个标志位,解析到name标签时改变标志位
  14.  
  15. @Override
  16. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  17. if(qName.equals("name")){
  18. flag=true;
  19. }
  20. }
  21.  
  22. @Override
  23. public void endElement(String uri, String localName, String qName) throws SAXException {
  24. if(qName.equals("name")){
  25. flag=false;
  26. }
  27. }
  28.  
  29. @Override
  30. public void characters(char[] ch, int start, int length) throws SAXException {
  31. if(flag==true){
  32. System.out.println(new String(ch,start,length));
  33. }
  34. }
  35.  
  36. }

结果输出为:

  1. lz
  2. zhanshang

得到某一个标签的值

  1. /**
  2. * 获得第二个name标签的值
  3. */
  4. @Test
  5. public void fun3()throws Exception{
  6. SAXParserFactory factory=SAXParserFactory.newInstance();
  7. SAXParser parser = factory.newSAXParser();
  8. parser.parse("src/person.xml", new MyHandler3());
  9. }
  10.  
  11. class MyHandler3 extends DefaultHandler{
  12.  
  13. private boolean flag=false;
  14.  
  15. private int index=1;
  16.  
  17. @Override
  18. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  19. if(qName.equals("name")){
  20. flag=true;
  21. }
  22. }
  23.  
  24. @Override
  25. public void endElement(String uri, String localName, String qName) throws SAXException {
  26. if(qName.equals("name")){
  27. flag=false;
  28. index++;
  29. }
  30. }
  31.  
  32. @Override
  33. public void characters(char[] ch, int start, int length) throws SAXException {
  34. if(flag==true&&index==2){
  35. System.out.println(new String(ch,start,length));
  36. }
  37. }
  38.  
  39. }

结果输出为:

  1. zhanshang

jaxp使用笔记的更多相关文章

  1. Javaweb学习笔记——(六)——————xml中jaxp两种解析方式和dom4j运用

    1.xml的scheam约束 dtd的语法:<!ElEMENT 元素名称 约束> **schema符合xml的语法,xml语句 **一个xml中可以有多个schema,多个schema使用 ...

  2. 超全面的JavaWeb笔记day05<xml&dtd&jaxp>

    0.表单提交方式(*****) button提交 超链接提交 事件 1.xml简介和应用(了解) 2.xml文档声明和乱码解决(*****) 文档声明 必须放在第一行第一列 设置xml编码和保存编码一 ...

  3. Android笔记——Android中数据的存储方式(二)

    我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效 ...

  4. spring 入门笔记(一)

    最近学习spring 通过笔记形式加深自己对spring的理解,也希望能跟各位入门者分享和讨论. 一.下载spring 下载spring也费了不少功夫,目前还没从spring官网找到下载入口,我从下面 ...

  5. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

  6. day0203 XML 学习笔记

    day02, 03 1. xml语言和作用 2. xml语法详解 2.1 xml 语法声明 2.1.1 encoding 属性 2.1.2 standalone 属性 2.2 xml 元素(Eleme ...

  7. JAVA与DOM解析器提高(DOM/SAX/JDOM/DOM4j/XPath) 学习笔记二

    要求 必备知识 JAVA基础知识.XML基础知识. 开发环境 MyEclipse10 资料下载 源码下载   sax.dom是两种对xml文档进行解析的方法(没有具体实现,只是接口),所以只有它们是无 ...

  8. XML解析之JAXP

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  9. Digester学习笔记(一)转载

    本博文系转载,作者原文已经无法找到,感谢原作者的辛苦整理 Digester学习笔记(一) 在windows下开发程序,用M$提供的接口处理.ini文件或管理注册表的键值是非常方便的.在java平台上开 ...

随机推荐

  1. React-Native基础_4.View组件

    View组件 对应ios 的UIView android 中的view 使用要先导入View import { View } from 'react-native'; 使用就是View标签,可以添加S ...

  2. Python自定义大小截屏

    蝈蝈这两天正忙着收拾家当去公司报道,结果做PHP的发小蛐蛐找到了他,说是想要一个可以截图工具. 大致需要做出这样的效果. 虽然已经很久不写Python代码了,但是没办法,盛情难却啊,只好硬着头皮上了. ...

  3. xshell连接及优化

    xshell 连接 问题:当你的xshell与服务器连接不上时 1:可先排查道路通不通 正常: 不正常: 1:查看服务器ip正不正确 2:vmware 编辑-虚拟网络编辑器 3:windows服务  ...

  4. MYSQL 调优和使用必读

    转载自:http://blog.eood.cn/mysql#rd?sukey=fc78a68049a14bb29c60f21c5254b15a1a9234459cf25ff467de14129ca11 ...

  5. Jmeter用表格查看结果

    Sample#:编号类似id Start Time:开始时间 Thread Name:线程名称 Label:请求名称 Sample Time:取样时间ms Status:状态 Bytes:接受字节数 ...

  6. JSP学习(五)JSP标签

    JSP标签 jsp的常用标签有: <jsp:include>标签 <jsp:forward>标签 <jsp:param>标签 <jsp:include> ...

  7. U盘格式和对齐扇数(常识)

    一.文件系统常见的四种格式:FAT16.FAT32.NTFS.ExFAT. 虽然四种文件系统的存储方式和特性各不相同,但对于传输速度并不快的存储卡和U盘来说, 实际传输性能却大同小异,理论测试数据相差 ...

  8. LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*

    LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...

  9. 【oracle】Oracle中as关键字

    在Oracle中as关键字不能用于指定表的别名 在Oracle中指定表的别名时只需在原有表名和表的别名之间用空格分隔即可 但as关键字可以用于指定列的别名 但在存储过程中如果列的别名与原有列名相同,在 ...

  10. distinct和group by的性能比较

    distinct和group by的性能比较 当去重复的字段 的个数比较多的时候,group by 比distinct要快很多 当去重复的字符 的个数比较少的时候,distinct 比group by ...