一、XML解析的技术
- DOM
- SAX
针对这两种解析技术,官方以及其他组织提供了不同的实现方式
常见的解析方式有如下三种:
a. sun公司提供的jaxp
b. dom4j组织提供的dom4j
c. jdom组织提供的jdom
二、dom VS sax
dom方式解析
* 根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象
* 缺点:如果文件过大,造成内存溢出
* 优点:很方便实现增删改操作
sax方式解析
* 采用事件驱动,边读边解析:从上到下,一行一行的解析,解析到某一个对象,返回对象名称
* 缺点:不能实现增删改操作
* 优点:如果文件过大,不会造成内存溢出,方便实现查询操作
三、jaxp所依赖的类
jaxp是javase的一部分
jaxp解析器在jdk的javax.xml.parsers包里面
Dom技术所依赖的两个类:
DocumentBuilderFactory: 解析器工厂类。这是一个抽象类,不能实例化
通过newInstance() 方法来获取 DocumentBuilderFactory 的实例。
DocumentBuilder : 解析器类。这个类也是一个抽象类,不能实例化
此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder() 方法获取
sax技术所依赖的两个类:
SAXParserFactory: 解析器工厂。实例 newInstance() 方法得到
SAXParser:解析器类。实例可以从 SAXParserFactory.newSAXParser() 方法获得
四、jaxp利用DOM技术解析XML文件实例
现有如下xml文件
zhangsan
lisi
m
操作一:查询xml文件中所有name元素的文本值
private static void selectAll() throws Exception {
//创建解析器工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//获取解析器对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
//获取解析后的document对象
Document doc = builder.parse("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml");
//获取所有name元素
NodeList list = doc.getElementsByTagName("name");
//输出name元素中的文本对象值
Node temp = null;
for(int i=0; i
所用到的方法:
DocumentBuilderFactory.newInstance():创建解析器工厂类实例
builderFactory.newDocumentBuilder():创建解析器实例
builder.parse:解析器调用解析方法,返回解析后的Document对象
doc.getElementsByTagName("标签名"):document对象调用该方法,获取所有指定标签名的标签,返回类型为NodeList
list.getLength():NodeList对象调用该方法,返回该List的长度
list.item(索引):NodeList对象调用该方法,根据下标返回指定Node对象
getTextContent():标签对象调用该方法,返回该标签的文本值
操作二:在第一个p元素中插入一个gender元素,其中gender元素的文本值为f
public static void addGender() throws Exception{
//获取解析器工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//获取解析器对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
//获取解析后的document对象
Document doc = builder.parse("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml");
//获取第一个p元素
NodeList list = doc.getElementsByTagName("p");
Node p1 = list.item(0);
//创建一个gender元素对象
Element gender1 = doc.createElement("gender");
//创建一个文本对象
Text text1 = doc.createTextNode("f");
//将文本对象加入gender元素
gender1.appendChild(text1);
//将gender元素加入到p元素
p1.appendChild(gender1);
//获取回写工厂对象
TransformerFactory transformerFactory = TransformerFactory.newInstance();
//获取回写对象
Transformer transformer = transformerFactory.newTransformer();
//调用回写方法将内存中的document对象写入到xml文件
transformer.transform(new DOMSource(doc), new StreamResult("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml"));
}
所用到的方法:
doc.createElement("标签名"):Document对象调用该方法,返回创建好的标签对象
doc.createTextNode("文本值"):Document对象调用该方法,返回创建好的文本对象
appendChild(对象名):父类对象调用该方法,将指定对象名的对象插入到该父类对象
TransformerFactory.newInstance():获取回写工厂类对象
transformerFactory.newTransformer():获取回写对象
transformer.transform(new DOMSource(doc), new StreamResult("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml")):
回写对象调用该回写方法,参数分别为源对象,和目的对象
参数一:Source的实现类
参数二:Result的实现类
操作三:修改第一个gender元素中的content对象为m
public static void modifyGender() throws Exception{
//获取解析器工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//获取解析器对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
//获取解析后的document对象
Document doc = builder.parse("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml");
//获取第一个gender元素
Node gender = doc.getElementsByTagName("gender").item(0);
//使用setTextContent方法修改文本对象内容
gender.setTextContent("m");
//回写
TransformerFactory formerFactory = TransformerFactory.newInstance();
Transformer transformer = formerFactory.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml"));
}
用到的方法:
setTextContent("文本内容"):标签对象调用该方法,修改自己的文本值
操作四:删除第一个p1元素下面的gender元素
public static void removeGender() throws Exception{
//获取解析器工厂对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//获取解析器 对象
DocumentBuilder builder = builderFactory.newDocumentBuilder();
//获取解析后的document对象
Document doc = builder.parse("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml");
//获取gender元素
Node gender = doc.getElementsByTagName("gender").item(0);
//获取gender得父节点
Node p = gender.getParentNode();
//父节点使用removeChild方法
p.removeChild(gender);
//回写
TransformerFactory formerFactory = TransformerFactory.newInstance();
Transformer transformer = formerFactory.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult("F:/MyEclipse10.7/Day05/src/testJaxp/person.xml"));
}
用到的方法:
getParentNode():标签对象调用该方法,获取自己的父标签
removeChild(标签对象名):父标签调用该方法,删除指定标签名的子标签
五、jaxp利用SAX技术解析XML文件实例
- 创建解析器,并执行parse方法的实例
public class TeachSax {
public static void main(String[] args) throws Exception {
/*
* 1、创建解析器工厂
* 2、创建解析器
* 3、执行parse方法
* */
//创建解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//创建解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//执行parse方法
saxParser.parse("F:/MyEclipse10.7/Day06/src/zuobiao/sax/person.xml", new MyDefault1());
}
}
/**
自己创建一个类,继承DefaultHandler
重写类里面的三个方法(有时候需要5个)
*/
class MyDefault1 extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) 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));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.print(""+qName+">");
}
}
用到的方法:
SAXParserFactory.newInstance():创建解析类工厂对象
saxParserFactory.newSAXParser():获取解析类对象
parse(参数1, 参数2):解析XML文档
两个参数
- 第一个参数:xml的路径
- 第二个参数:事件处理器(该处理器需要继承自DefaultHandler,并重写里面的方法)
事件处理类:
DefaultHandler
- startDocument:当XML文档开始解析时该方法被自动调用
- startElement:当开始解析一个元素时,该方法被自动调用
- characters:当解析到文本内容时,该方法被自动调用
- endElement:当解析一个元素结束时,该方法被自动调用
- endDocument:当XML文档解析结束时该方法被自动调用
- sax解析xml文档操作实例
现有如下xml文件
zhangsan
20
lisi
30
操作一:输出xml文件中的所有内容
事件处理类如下:
class MyDefaultHandler1 extends DefaultHandler{
@Override
public void startDocument() throws SAXException {
System.out.println("");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) 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));
}
@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));
}
}
main方法中调用:
public class TestSax {
public static void main(String[] args) throws Exception{
//获取SaxParserFactory对象
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//获取SaxParser对象
SAXParser parser = saxParserFactory.newSAXParser();
//使用parser方法解析xml文件
parser.parse("F:/MyEclipse10.7/Day06/src/zuobiao/sax/person.xml", new MyDefaultHandler1());
}
}
操作二:输出指定索引的name标签文本值
事件处理类如下:
class MyDefaultHandler2 extends DefaultHandler{
boolean flag = false; //使用标记来记录是否为name标签
int index = 0; //使用index来继承name标签的索引值
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if("name".equals(qName)){
this.flag = true;
index++;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(flag && (index==2)){
System.out.println(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("name".equals(qName)){
this.flag = false;
}
}
}
main方法中调用同上,故省略。
参考博文在此
Java新手,若有错误,欢迎指正!