****1.XML解析的简介:
(1)xml是标记性文档
(2)js中使用dom方式解析标记性文档
(3)xml的解析技术:dom和sax
2.dom解析和sax解析的区别:
dom解析:根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象
**(1)优点:**便于实现增删查改
**(2)缺点:**如果文件过大,会造成内存溢出
sax解析:采用时间驱动,边读边解析
——从上到下,一行一行解析,解析到某个对象时,返回对象名称
**缺点:**不能实现增删改操作
**优点:**在文件过大的情况下也不会造成内存溢出,方便实现查询操作
3.xml解析器
不同的公司和组织提供了不同的解析器:
常用的有sun公司的jaxp,和dom4j
4.jaxpAPI简介:
jaxp是javase的一部分
jaxp解析器在jdk的javax.xml.parsers包里面:
——四个类:分别是针对dom和sax解析使用的类
dom:
DocumentBuilder : 解析器类
- 这个类是一个抽象类,不能new,此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder() 方法获取
- 一个方法,可以解析xml parse("xml路径") 返回是 Document 整个文档
- 返回的document是一个接口,父节点是Node,如果在document里面找不到想要的方法,到Node里面去找
- 在document里面方法
getElementsByTagName(String tagname)
-- 这个方法可以得到标签
-- 返回集合 NodeList
createElement(String tagName)
-- 创建标签
createTextNode(String data)
-- 创建文本
appendChild(Node newChild)
-- 把文本添加到标签下面
removeChild(Node oldChild)
-- 删除节点
getParentNode()
-- 获取父节点
NodeList list
- getLength() 得到集合的长度
- item(int index)下标取到具体的值
for(int i=0;i<list.getLength();i++) {
list.item(i)
}
getTextContent()
- 得到标签里面的内容
DocumentBuilderFactory: 解析器工厂
- 这个类也是一个抽象类,不能new
newInstance() 获取 DocumentBuilderFactory 的实例。
5.使用jaxp解析xml
首先先给出实例的xml文件
xml文件名为:person.xml,在src目录下
<person>
<p1>
<name nameId="1" nameId2 ="n1">lisi</name>
<age ageId="12">12</age>
</p1>
<p1>
<name nameId= "2" nameId2="n2">wangwu</name>
<age ageId="1234">13</age>
</p1>
</person>
应用一:获取person.xml中的name元素
@Test
public void test1() throws Exception {
//创建解析器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//根据解析器工厂创建解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//解析xml返回Document对象
Document docuemtn = documentBuilder.parse("src/person.xml");
//获得所有的name元素
NodeList list=document.getElementsByTagName("name);
for(int i=0;i<list.getLength();i++) {
//得到每一个节点
Node node = list.item(i); //从节点集合中获取对应的节点
//获得标签中文本的信息
//node.getTextContent():获取节点的信息
System.out.println(node.getTextContent());
}
}
应用二:查询xml中第一个name元素的值
public void test2 () throws Exception {
//获得解析器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstace();
//根据解析器工厂获得解析器
DocumentBuilder documentBuilder = documeBuilderFactory.newDocuementBuilder();
//解析文件
Document document = documentBuilder.parse("src/person.xml)
//根据标签名获得对应的标签集合
NodeList list = document.getElementsByTagName("name");
//根据下标获得第一个元素的节点
Node node = list.item(0);
//获取内容
String text = node.getTextContent();
System.out.println(text)
}
应用三:在第一个p1下创建一个sex节点
public void test3() throws Exception{
//获得解析器工厂
DocumentBuilderFactory docuFactory = DocumentBuilderFactory.newInstance();
//获得解析器
DocumentBuilder documentBuilder = docuFactory.newDocumentBuilder();
//解析xml,获得document
Document document = documentBuilder.parse("src/person.xml");
//获得所有名字为p1的标签
NodeList list = document.getElementsByTagName("p1);
//根据下标获得第一个p1的标签
Node node = list.item(0);
//createElement:创建一个节点
Element sex = document.createElement("sex");
//创建文本内容
Text text1 = document.createTextNode("nv");
//将文本加入到创建的节点下
sex.appendChild(text1);
//将创建的标签加入到p1下
node.appendChild(sex);
//回写到xml文件中
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transform = transformerFactory.newTransformer();
transform.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
应用四:修改节点
@Test
public void test4() throws Exception {
//获得解析器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//获得解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//解析xml文件
Document document = documentBuilder.parse("src/person.xml");
//获取要修改的节点
NodeList list = document.getElementsByTagName("sex");
Node node = list.item(0);
//修改节点内容
node.setTextContent("man");
//回写
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
应用五:删除应用四添加的sex节点:
@Test
public void test5 () {
//获得解析器工厂
DocumentBuilderFactorty documentBuilderFactory = DocumentBuilderFactory.newInstance();
//根据解析器工厂
DoucmentBuilder documentBuilder = documentBuilderFactory.newDocuemntBuider();
//解析xml文件
Document document = documentBuilder.parse("sec/person.xml");
//获得要删除的sex节点
Node sex = document.getElementsByTagName("sex").item(0);
//获得父节点
Node p1 = sex.getParentNode();
//删除节点
p1.removeChild(sex);
//回写到xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
注意:删除节点,只能由被删除节点的父节点删除
//遍历节点:
@Test
public void test6() throws Exception {
//获得解析器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//获得解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//解析xml
Document document = documentBuilder.parse("src/person.xml");
list1(document);
}
private static void list1(Node node) {
if(node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(node.getNodeName());
}
NodeList list = node.getChildNodes();
for(int i =0;i<list.getLength();i++) {
Node node1 = list.item(i);
list1(node1);
}
}
注意:在使用jaxp解析xml时需要从如下的包中导入类库,如果出现错误,请检查导入的包是否正确
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
6使用jaxp用sax方式解析xml
sax:
SAXParser:解析器类
SAXParserFactory: 解析器工厂
public class TestSax {
@Test
public void test() throws Exception {
//获取解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//获得解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//解析
saxParser.parse("src/p1.xml", new MyDefault1());
}
}
class MyDefault1 extends DefaultHandler{
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//qName:开始标签的名字
//attributes:标签的属性
System.out.print("start:"+qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//获得文本内容,通过创建字符串形式将文本内容转为字符串,可以输出
System.out.print("end:"+new String(ch, start, length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
//qName:结束标签的名字
System.out.println("end: "+qName);
}
}
注意:使用saxParser解析器解析xml文件时,需要传入继承了DefaultHandler类的自己定义的类的实例,也可以直接传入DefaultHandler类的实例,但是自己创建一个继承了DefaultHandler的类可以实现自己需要的功能
当解析到开始标签时候,自动执行startElement方法
当解析到文本时候,自动执行characters方法
当解析到结束标签时候,自动执行endElement方法
7.使用dom4j解析xml
步骤:1:导入相关的jar包: dom4j-1.6.1.jar
2:创建解析器
3:得到根节点
4:得到需要的标签
得到document
SAXReader reader = new SAXReader();
Document document = reader.read(url);
* document的父接口是Node
* 如果在document里面找不到想要的方法,到Node里面去找
* document里面的方法 getRootElement() :获取根节点 返回的是Element
* Element也是一个接口,父接口是Node
- Element和Node里面方法
** getParent():获取父节点
** addElement:添加标签
* element(qname)
** 表示获取标签下面的第一个子标签
** qname:标签的名称
* elements(qname)
** 获取标签下面是这个名称的所有子标签(一层)
** qname:标签名称
* elements()
** 获取标签下面的所有一层子标签
本次解析的xml文件为p1.xml,在src下
文件内容:
<person>
<p1 id="aaa">
<name>lisi</name>
<age>300</age>
</p1>
<p1 id="333">
<name>wangwu</name>
<age>12</age>
</p1>
</person>
应用一:查询第一个name元素
@Test
public void test1() throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//得到document
Document document = saxReader.read("src/p1.xml"); //需要进行异常的处理
//得到根节点
Element root = document.getRootElement();
//获得文件中的p1标签
List<Element> list = root.elements("p1");
//遍历list
for(Element element :list) {
//element是每一个p1元素
//得到p1下面的name元素
Element name1 = element.element("name");
//获取name里面的值
String s = name1.getText();
System.out.println(s);
}
}
应用二:获取一个name元素的文本
@Test
public void test2() throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//得到document
Document document =saxReader.read("src/p1.xml");
//得到根节点
Element root = document.getRootElement():
//得到第一个p1
//使用element("标签名")获得一个标签,elements("标签名")获得所有的该标签
Element p1 = root.element("p1");
//获得p1下的name元素
Element name1 = p1.element("name");
//获取name的文本值
String text = name1.getText();
System.out.println(text);
}
应用三:获取第二个name元素的值
@Test
public void test3() throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//获得document
Document document = saxReader.read("src/p1.xml");
//获得根节点
Element root = document.getRootElement();
//获得所有的p1元素
List<Element> list = root.elements("p1");
//获得第二个p1
Element p1 = list.get(1);
//得到p1下面的name
Element name2 = p1.element("name");
//获取name标签的文本值
String text = name2.getText();
System.out.println(text);
}
应用四:向第一个p1标签中添加nv
@Test
public void test4() throws Exception {
//获得解析器
SAXReader reader = new SAXReader();
//获得document
Document document = reader.read("src/p1.xml");
//获得根节点
Element root = document.getRootElement();
//获得第一个p1标签
Element p1 = root.element("p1");
//添加标签
Element sex = p1.addElement("sex");
sex.addText("nv");
//回写到xml文件中
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileOutputStream("src/p1.xml"),format);
writer.write(document);
writer.close();
}
应用五:向指定位置添加标签
@Test
public void test5() throws Exception {
//获得解析器
SAXReader reader = new SAXReader();
//获得document
Document document = reader.read("src/p1.xml");
//获得根节点
Element root = document.getRootElement();
//获得第一个p1元素
Element p1 = root.element("p1");
//获得p1下的所有字标签
List<Element> list = p1.elements();
//创建一个标签
Element school = DocumentHelper.createElement("school");
school.setText("hist");
//在指定位置添加元素
list.add(1,school);
//回写
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileOutputStream("src/p1.xml"), format);
writer.write(document);
writer.close();
}
应用六:修改节点
@Test
public void test6() throws Exception{
//获得解析器
SAXReader reader = new SAXReader();
//获得document
Document document = reader.read("src/p1.xml");
//获取根节点
Element root = document.getRootElement();
//获得p1节点
Element p1 = root.element("p1");
//获得age节点
Element age = p1.element("age");
//修改文本值
age.setText("300");
//回写
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileOutputStream("src/p1.xml"), format);
writer.write(document);
writer.close();
}
应用七:删除指定的节点
@Test
public void test7() throws Exception {
//获得解析器
SAXReader reader = new SAXReader();
//获得document
Document document= reader.read("src/p1.xml");
//获取根节点
Element root = document.getRootElement();
//获得p1节点
Element p1 = root.element("p1");
//获得p1下想要删除的节点.例如school
Element sch = p1.element("school");
//通过school节点的父节点删除数据
// sch.getParent().remove(sch);
//由于school的父节点p1已经获得,所以可以直接使用p1删除节点
p1.remove(sch);
//回写
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileOutputStream("src/p1.xml"), format);
writer.write(document);
writer.close();
}
8.使用dom4j支持的xpath的操作解析xml文件
首先,简单介绍xpath的几种语法形式:
* 第一种形式
/AAA/DDD/BBB: 表示一层一层的,AAA下面 DDD下面的BBB
* 第二种形式
//BBB: 表示和这个名称相同,表示只要名称是BBB,都得到
* 第三种形式
/*: 所有元素
* 第四种形式
** BBB[1]: 表示第一个BBB元素
×× BBB[last()]:表示最后一个BBB元素
* 第五种形式
** //BBB[@id]: 表示只要BBB元素上面有id属性,都得到
* 第六种形式
** //BBB[@id='b1'] 表示元素名称是BBB,在BBB上面有id属性,并且id的属性值是b1
使用前提:默认的情况下,dom4j不支持xpath,如果想要在dom4j里面是有xpath,第一步需要,引入支持xpath的jar包,使用 jaxen-1.1-beta-6.jar,然后将jar包导入到项目中
在dom4j里面提供了两个方法,用来支持xpath
*** selectNodes(“xpath表达式”)
- 获取多个节点
*** selectSingleNode(“xpath表达式”)
- 获取一个节点
应用一:查询xml文件中所有的name元素的值
@Test
public void test1() throws Exception {
//获取解析器
SAXReader saxReader = new SAXReader();
//解析xml,获得document
Document document = saxReader.read("src/p1.xml");
//selectNodes可以根据Xpath获取多个元素
//通过selectNodes方法,使用Xpath语法获取所有的name节点元素
List<Node> list = document.selectNodes("//name");
//遍历
for(Node node :list) {
//获取节点的文本
String s = node.getText();
System.out.println(s);
}
}
应用二:获取p1.xml中第一个p1(带有属性 ‘aaa’)元素下的name元素
@Test
public void test2() throws Exception {
//获取解析器
SAXReader reader = new SAXReader();
//解析xml,获得document
Document document = reader.read("src/p1.xml");
//selectSingleNode方法可以获取一个Node元素
Node name1 = document.selectSingleNode("//p1[@id='aaa']/name");
String s = name1.getText();
System.out.println(s);
}
注意:写程序时,注意导入的包正确。