JavaScripts学习日记——DOM SAX JAXP DEMO4J XPath

今日关键词:

XML解析器

DOM

SAX

JAXP

DEMO4J

XPath

XML解析器

1.解析器概述

什么是解析器

  XML是保存数据的文件,XML中保存的数据也需要被程序读取然后使用。那么程序使用什么来读取XML文件中的数据呢?XML解析器!例如.properties文件的解析器是Properties类一样!

  XML不只被Java语言使用,还被C++、C#、Javascript等等语言使用,所以解析XML不是一门语言的工作!

DOM和SAX介绍

主流的XML解析有两种标准:DOM和SAX。它们是标准,是思想,不是真正的解析器,它们是跨语言的!!!

l  DOM(Document Object Model):W3C组织提供的解析XML文档的标准接口;

l  SAX(Simple API for XML):(草民)社区讨论的产物,是一种事实上的标准。

Apache的xerces组件实现了DOM和SAX,所以在我们在Java中解析XML需要使用xerces(JDK提供了)。所以我们称xerces是DOM、SAX解析器。

2.1 DOM解析原理

DOM要求解析器把整个XML文档装载到一个Document对象中。即使用DOM解析器解析XML文档的结果就是一个Document对象。

一个XML文档解析后对应一个Document对象,可以通过Document对象获取根元素,然后在通过根元素获取根元素的子元素…,这说明DOM解析方式保留了元素之间的结构关系(DOM树)!

l  优点:元素与元素之间的结构关系保留了下来;

l  缺点:如果XML文档过大,那么把整个XML文档装载进内存,可能会出现内存溢出的现象!

2.2 SAX解析原理

DOM解析后的结果是一个Document对象,而SAX解析没有结果!SAX要求在开始解析之前用户提供一个接口的实现对象,然后把接口实现对象传递给SAX解析器,然后在SAX解析器的过程中不调用实现对象的方法。

l  DOM是解析时把数据放到了Document对象中,然后用户从Document中获取需要的数据;

l  SAX要求用户参与到解析过程中来,把想要做的事情写到接口实现对象中,然后SAX在解析过程中来调用接口实现对象的方法。

你看过三国么?听说过三气周瑜么?其中二气周瑜你知道么?故事情节大致如下:

倒霉的周瑜让孙权把自己的妹妹嫁给刘备,让刘备来吴国完婚!目的是把刘备软禁在吴国,或者把刘备干掉。如果刘备不同意,那么孙权就有了打刘备,抢荆州的借口了。

孔明识破了这一计,最终让刘备与赵云去吴国。但孔明给了赵云三个锦囊:

l  到了吴国南徐开第一个锦囊;

l  在吴国住到年终开第二个锦囊;

l  回家途中被吴军阻拦开第三个锦囊。

锦囊的内容是什么呢?赵云和刘备性命如何呢?诸葛亮又是如何二气周瑜的呢?这里没有了,自己去买本《三国演义》看吧!

其中赵云就是SAX解析器,赵负责去吴国,SAX负责解析XML;

其中孔明的三个锦囊就是接口实现中的三个方法;

赵云会在特定时刻打开锦囊,依计而行,SAX解析器会在解析过程中特定时刻调用接口实现中的某一方法。

取亲之旅 ßà 被解析的XML

赵云 ßà SAX解析器

锦囊 ßà接口在三个方法(由我们完成)

赵云在取亲之旅中,会在发生特定事件时,执行特定的锦囊。例如在到达吴国南徐时,执行第一个锦囊上的妙计。

SAX解析器会在解析XML文档的过程中,在发生特定事件时,调用接口中特定的方法。例如在SAX解析到某个元素的开始标签时,输出元素名称!其中解析到开始标签就是特定的事件,而输出元素名称,就是接口中方法的实现。

接口中方法如下:


public void startDocument()[崔1] ;

public void endDocument()[崔2] ;

public void startElement(String uri, String localName, String qName,

Attributes atts)[崔3] ;

public void endElement(String uri, String localName, String qName)[崔4]

public void characters(char[] ch, int start, int length)[崔5] ;

public void ignorableWhitespace(char[] ch, int start, int length)[崔6] ;

public void processingInstruction(String target, String data)[崔7] ;

  接口的实现由我们来完成,然后我们需要把接口实现类对象“交给”SAX解析器,然后让SAX开始解析。SAX会在特定事件发生时,调用接口中的方法,完成我们交给它的任务。

l  优点:适合解析大XML文件(内存空间占用小),因为是解析一行处理一行,处理完了就不需要在保留数据了;

l  缺点:因为是解析一行处理一行,解析之后数据就丢失了,所以元素与元素之间的结构关系没有保留下来。

JAXP介绍(不重要)

我们知道有很多像xerces一样的解析器,都对DOM和SAX提供了实现,那么如果我们在项目中一开始使用了解析A,然后因为某些原因想更换成解析B,那么就需要修改项目。

JAXP(Java API for XML Processing)是由Java提供的,JAXP是对所有像xerces一样的解析的提供统一接口的API。

当我们使用JAXP完成解析工作时,还需要为JAXP指定xerces或其他解析器,当需要更换解析器时,无需修改代码,只需要修改配置即可。

  JAXP不是解析器,但使用它可以方便的切换解析器。所以在我们的程序中只会使用JAXP,而不会直接使用Xeces。

JDOM和DOM4j介绍

DOM和SAX是跨语言的XML解析准备,在Java中使用并不方便。而JDOM和DOM4j是专门为Java语言提供的解析工具!使用起来很方便,所以真实开发中使用JDOM或DOM4J比较多。

又因为DOM4J与JDOM比较结果为DOM4j完胜,所以我们这里只会对DOM4j介绍,而不会介绍JDOM。

2.DOM和SAX解析

1 DOM结构模型

DOM中的核心概念就是节点,在XML文档中的元素、属性、文本、处理指令,在DOM中都是节点!

2 JAXP之DOM解析

使用DOM解析XML的目标就是获取到Document对象,然后在从Document中获取到需要的数据。Document对象就是XML文档在内存中的样子。

  1. 获取Document三步:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();[崔8]

DocumentBuilder builder = factory.newDocumentBuilder();[崔9]

Document document = builder.parse(new File("students.xml"));[崔10]

  1. 遍历Document:

@Test

public void fun1() throws SAXException, IOException, ParserConfigurationException {

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document document = builder.parse(new File("src/students.xml"));

// 获取根元素

Element rootEle = document.getDocumentElement();

// 获取元素的所有子节点

NodeList nodeList = rootEle.getChildNodes();

// 循环遍历所有节点

for(int i = 0; i < nodeList.getLength(); i++) {

// 获取其中每个节点

Node node = nodeList.item(i);

// 判断节点的类型是否为元素

if(node.getNodeType() == Node.ELEMENT_NODE) {

// 强转成元素类型

Element stuEle = (Element) node;

// 获取元素的名称

String eleName = stuEle.getNodeName();

// 获取元素的number属性值

String number = stuEle.getAttribute("number");

// 获取名为name的子元素,因为返回值为NodeList,

// 所以需要使用item(0)方法获取第一个name子元素

// getTextContent()是获取节点的文本内容

String name = stuEle.getElementsByTagName("name").item(0).getTextContent();

String age = stuEle.getElementsByTagName("age").item(0).getTextContent();

String sex = stuEle.getElementsByTagName("sex").item(0).getTextContent();

System.out.println(eleName + ":[number=" + number + ", name=" + name + ", age=" + age + ", sex=" + sex + "]");

}

}

}

3 JAXP之SAX解析

使用SAX解析XML文档需要先给出DefualtHandler的子类,重写其中的方法。然后在使用SAX开始解析时把DefaultHandler子类对象传递给SAX解析器。


class MyContentHandler extends DefaultHandler {

public void startDocument() throws SAXException {

System.out.println("开始解析...");

}

public void endDocument() throws SAXException {

System.out.println("解析结束...");

}

public void startElement(String uri, String localName, String qName,

Attributes atts) throws SAXException {

System.out.println(qName [崔11] + "元素解析开始");

}

public void endElement(String uri, String localName, String qName)

throws SAXException {

System.out.println(qName [崔12] + "元素解析结束");

}

public void characters(char[] ch, int start, int length)

throws SAXException {

System.out.print(new String(ch, start, length)[崔13] .trim());

}

}

使用SAX解析首先需要获取工厂,再通过工厂获取解析器对象,然后使用解析对象完成解析工作:


SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

parser.parse(new File("src/students.xml"), new MyContentHandler());

3.DOM4J解析(崔老师版)

1 DOM4J概述

DOM4J是针对Java开发人员专门提供的XML文档解析规范,它不同与DOM,但与DOM相似。DOM4J针对Java开发人员而设计,所以对于Java开发人员来说,使用DOM4J要比使用DOM更加方便。

在DOM4J中,也有Node、Document、Element等接口,结构上与DOM中的接口比较相似。但它们是不同的类:

l  Node

  • Attribute:表示属性节点;
  • Branch:表示可以包含子元素的节点:

n  Document:表示整个文档;

n  Element:表示元素节点;

  • CharacterData:表示文本节点:

n  Text:表示文本内容;

n  CDATA:表示CDATA段内容;

n  Comment:表示注释内容。

  我们再次强调,DOM和DOM4J是不同的,DOM中的Document是org.w3c.Document,而DOM4J中的Document是org.dom4j.Document,它们是不同的类,其他Node、Element也是一样。

2 读取、保存、创建Document

使用dom4j需要导入:

l  dom4j.jar

l  jaxen.jar

  1. 读取

SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

  1. 保存XML文档

// 创建格式化器,使用\t缩进,添加换行

OutputFormat format = new OutputFormat("\t", true);

// 清空数据中原有的换行

format.setTrimText(true);

// 创建XML输出流对象

XMLWriter writer = new XMLWriter(new FileWriter("src/a.xml"), format);

// 输出Document

writer.write(doc);

// 关闭流

writer.close();

  1. 创建Document

Document doc = DocumentHelper.createDocument();

3 遍历Document


public void fun1() throws DocumentException {

SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

// 获取根元素

Element rootEle = doc.getRootElement();

// 获取根元素的所有子元素

List<Element> eleList = rootEle.elements();

// 遍历元素集合

for (Element stuEle : eleList) {

// 获取元素名称

String eleName = stuEle.getName();

// 获取元素的number属性值

String number = stuEle.attributeValue("number");

// 获取元素的name子元素内容

String name = stuEle.elementText("name");

// 获取元素的age子元素内容

String age = stuEle.elementText("age");

// 获取元素的sex子元素内容

String sex = stuEle.elementText("sex");

System.out.println(eleName + ": [number=" + number + ", name="

+ name + ", age=" + age + ", sex=" + sex + "]");

}

}

4 添加student元素


SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

// 获取根元素<students>

Element root = doc.getRootElement();

// 为root添加名为student的子元素,并返回这个新添加的子元素

Element stuEle = root.addElement("student");

// 给元素添加属性number,值为123

stuEle.addAttribute("number", "123");

// 添加子元素name,并设置name子元素的文本内容为wangWu

stuEle.addElement("name").setText("wangWu");

stuEle.addElement("age").setText("30");

stuEle.addElement("sex").setText("male");

//////////////////

// 创建格式化器,使用\t缩进,添加换行

OutputFormat format = new OutputFormat("\t", true);

// 清空数据中原有的换行

format.setTrimText(true);

// 创建XML输出流对象

XMLWriter writer = new XMLWriter(new FileWriter("src/a.xml"), format);

// 输出Document

writer.write(doc);

// 关闭流

writer.close();

5 查询元素


SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

/*

* selectSingNode()方法的参数是XPath

* XPath是在XML文档中查找的一门表达式语言

* “//”表示查找整个XML文档

* student表示查找名为student的元素

* []表示条件

* @number表示number属性

* @number=‘ITCAST_1001‘表示条件为number属性等于ITCAST_1001

*

* selectSingNode()方法在查找到多个满足XPath的元素时,只返回第一个。

*/

Element stuEle1 = (Element)doc.selectSingleNode("//student[@number=‘ITCAST_1001‘]");

// 把元素转换成字符串

System.out.println(stuEle1.asXML());

// 查找name子元素内容为liSi的student元素

Element stuEle2 = (Element) doc.selectSingleNode("//student[name=‘liSi‘]");

System.out.println(stuEle2.asXML());

6 修改元素


SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

// 查找元素

Element stuEle = (Element)doc.selectSingleNode("//student[@number=‘ITCAST_1001‘]");

// 修改student元素的name子元素内容为“张三”

stuEle.element("name").setText("张三");

//////////////////

// 创建格式化器,使用\t缩进,添加换行

OutputFormat format = new OutputFormat("\t", true);

// 清空数据中原有的换行

format.setTrimText(true);

// 创建XML输出流对象

XMLWriter writer = new XMLWriter(new FileWriter("src/a.xml"), format);

// 输出Document

writer.write(doc);

// 关闭流

writer.close();

7 删除学生元素


SAXReader reader = new SAXReader();

Document doc = reader.read("src/students.xml");

// 查找元素

Element stuEle = (Element)doc.selectSingleNode("//student[@number=‘ITCAST_1001‘]");

// 获取父元素来删除元素

stuEle.getParent().remove(stuEle);

//////////////////

// 创建格式化器,使用\t缩进,添加换行

OutputFormat format = new OutputFormat("\t", true);

// 清空数据中原有的换行

format.setTrimText(true);

// 创建XML输出流对象

XMLWriter writer = new XMLWriter(new FileWriter("src/a.xml"), format);

// 输出Document

writer.write(doc);

// 关闭流

writer.close();

8 dom4j API介绍

Node方法:

l  String asXML():把当前节点转换成字符串,如果当前Node是Document,那么就会把整个XML文档返回;

l  String getName():获取当前节点名字;Document的名字就是绑定的XML文档的路径;Element的名字就是元素名称;Attribute的名字就是属性名;

l  Document getDocument():返回当前节点所在的Document对象;

l  short getNodeType():获取当前节点的类型;

l  String getNodeTypeName():获取当前节点的类型名称,例如当前节点是Document的话,那么该方法返回Document;

l  String getStringValue():获取当前节点的子孙节点中所有文本内容连接成的字符串;

l  String getText():获取当前节点的文本内容。如果当前节点是Text等文本节点,那么本方法返回文本内容;例如当前节点是Element,那么当前节点的内容不是子元素,而是纯文本内容,那么返回文本内容,否则返回空字符串;

l  void setDocument(Document doc):给当前节点设置文档元素;

l  void setParent(Element parent):给当前节点设置父元素;

l  void setText(String text):给当前节点设置文本内容;

Branch方法:

l  void add(Element e):添加子元素;

l  void add(Node node):添加子节点;

l  void add(Comment comment):添加注释;

l  Element addElement(String eleName):通过名字添加子元素,返回值为子元素对象;

l  void clearContent():清空所有子内容;

l  List content():获取所有子内容,与获取所有子元素的区别是,<name>liSi</name>元素没有子元素,但有子内容;

l  Element elementById(String id):如果元素有名为“ID”的属性,那么可以使用这个方法来查找;

l  int indexOf(Node node):查找子节点在子节点列表中的下标位置;

l  Node node(int index):通过下标获取子节点;

l  int nodeCount():获取子节点的个数;

l  Iterator nodeIterator():获取子节点列表的迭代器对象;

l  boolean remove(Node node):移除指定子节点;

l  boolean remove(Commont commont):移除指定注释;

l  boolean remove(Element e):移除指定子元素;

l  void setContent(List content) :设置子节点内容;

Document方法:

l  Element getRootElement():获取根元素;

l  void setRootElement():设置根元素;

l  String getXmlEncoding():获取XML文档的编码;

l  void setXmlEncoding():设置XML文档的编码;

Element方法:

l  void add(Attribute attr):添加属性节点;

l  void add(CDATA cdata):添加CDATA段节点;

l  void add(Text Text):添加Text节点;

l  Element addAttribute(String name, String value):添加属性,返回值为当前元素本身;

l  Element addCDATA(String cdata):添加CDATA段节点;

l  Element addComment(String comment):添加属性节点;

l  Element addText(String text):添加Text节点;

l  void appendAttributes(Element e):把参数元素e的所有属性添加到当前元素中;

l  Attribute attribute(int index):获取指定下标位置上的属性对象;

l  Attribute attribute(String name):通过指定属性名称获取属性对象;

l  int attributeCount():获取属性个数;

l  Iterator attributeIterator():获取当前元素属性集合的迭代器;

l  List attributes():获取当前元素的属性集合;

l  String attributeValue(String name):获取当前元素指定名称的属性值;

l  Element createCopy():clone当前元素对象,但不会copy父元素。也就是说新元素没有父元素,但有子元素;

l  Element element(String name):获取当前元素第一个名称为name的子元素;

l  Iterator elementIterator():获取当前元素的子元素集合的迭代器;

l  Iterator elementIterator(String name):获取当前元素中指定名称的子元素集合的迭代器;

l  List elements():获取当前元素子元素集合;

l  List elements(String name):获取当前元素指定名称的子元素集合;

l  String elementText(String name):获取当前元素指定名称的第一个元素文件内容;

l  String elementTextTrime(String name):同上,只是去除了无用空白;

l  boolean isTextOnly():当前元素是否为纯文本内容元素;

l  boolean remove(Attribute attr):移除属性;

l  boolean remove(CDATA cdata):移除CDATA;

l  boolean remove(Text text):移除Text。

DocumentHelper静态方法介绍:

l  static Document createDocument():创建Dcoument对象;

l  static Element createElement(String name):创建指定名称的元素对象;

l  static Attribute createAttrbute(Element owner, String name, String value):创建属性对象;

l  static Text createText(String text):创建属性对象;

l  static Document parseText(String text):通过给定的字符串生成Document对象;


[崔1]开始解析时调用该方法

[崔2]结束解析时调用该方法

[崔3]遇到元素的开始标签时调用该方法

[崔4]遇到元素结束标签时调用该方法

[崔5]遇到文本内容时调用该方法

[崔6]遇到元素与元素之间的空白时调用该方法

[崔7]遇到处理指令时调用该方法

[崔8]获取工厂

[崔9]获取解析器

[崔10]解析XML文档,得到Document对象

[崔11]元素名称

[崔12]元素名称

[崔13]当前文本内容

5.Xpath

XPath实际上就是一种更快的查找XML元素的方式。详情见文档。

时间: 2024-10-12 15:47:27

JavaScripts学习日记——DOM SAX JAXP DEMO4J XPath的相关文章

JavaScripts学习日记——DOM

DOM Document Object Model 文档对象模型  整合js和html css.控制html文档行为.DOM就是把页面当中所有内容全部封装成对象.HTML文档中万物皆对象. 1.对象的分类    Document ***    Element  ***    Attribute    Text    Common以上5类对象 具有一些共同特征 抽象出了一个父类    Node        自身属性            nodeName            nodeValue

Java解析XML汇总(DOM/SAX/JDOM/DOM4j/XPath)

[目录] 一.[基础知识——扫盲] 二.[DOM.SAX.JDOM.DOM4j简单使用介绍] 三.[性能测试] 四.[对比] 五.[小插曲XPath] 六.[补充] 关键字:Java解析xml.解析xml四种方法.DOM.SAX.JDOM.DOM4j.XPath [引言] 目前在Java中用于解析XML的技术很多,主流的有DOM.SAX.JDOM.DOM4j,下文主要介绍这4种解析XML文档技术的使用.优缺点及性能测试. 一.[基础知识——扫盲] sax.dom是两种对xml文档进行解析的方法(

JavaScripts学习日记——ECMAscript

1.Function对象 Function是一个很特殊的对象,特殊在该对象就像java中的方法一样,可以运行,可以传参数. 三种定义function对象的方法: 1.function fun1(a,b){       alert(a+b);           } 2.var fun2 = new Function("a","b","alert(a+b);");//最后一个参数代表函数体 3.var fun3 = function(a,b){  

JavaScripts学习日记——XML DTD Schema

今日关键词: XML DTD Schema 1.XML 1 XML的概述 1.1 什么是XML XML全称为Extensible Markup Language,意思是可扩展的标记语言.XML语法上和HTML比较相似,但HTML中的元素是固定的,而XML的标签是可以由用户自定义的. W3C在1998年2月发布1.0版本,2004年2月又发布1.1版本,但因为1.1版本不能向下兼容1.0版本,所以1.1没有人用.同时,在2004年2月W3C又发布了1.0版本的第三版.我们要学习的还是1.0版本!!

SAX,DOM,JAXP,JDOM,DOM4J比较

dom,sax,jdom,dom4j的技术特点: 1: DOMDOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.DOM 是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何 工作.由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的.DOM 以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何

J2EE学习之路---SAX与DOM4J

什么是SAX SAX,全称Simple API for XML,既是一种接口,也是一种软件包.它是一种XML解析的替代方法.SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析.由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势.我们将在dom4j的学习中使用到SAX,于是先对SAX进行了解. 如何使用SAX 与之前学习的DOM中解析器创建方法类似,利用工厂模式和单例模式的结合,创造出一个解析器的实例.下面是打开一个XML文件的示例代码: S

学习日记之状态模式和Effective C++

状态模式(State):当一个对象内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类. (1),状态模式主要负责解决的是当控制一个对象转换的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化. (2),状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来. (3),将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和

学习日记

五一耍了三天,自己的计划有泡汤,那种制止力哪里去了,不过我认真起来还有有废寝忘食的时候,不过希望这种时候多一点,回家妈妈告诉我,她给老师打电话了的,老师说了我的一些情况,不过我没有老师说的那么好,学习在班上算中等.我觉得还算不上吧!任重而道远吧. Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量

学习日记之解释器模式和Effective C++

解释器模式(interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. (1),如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言的句子.这样可以构建一个解释器,该解释器通过解释这些句子来解决该问题. (2),当一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象的语法树时,可使用解释器模式. (3),容易改变和扩展文法,因为该模式使用类来表示文法规则,你可以使用继承来改变和扩展该文法