XML解析(JAVA版)

本文深入讲解XML解析技术,包括DOM和SAX两种主要解析方式的特点和应用场景,详细演示了使用JAXP和DOM4J库解析及操作XML文件的具体方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

****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);
	}

注意:写程序时,注意导入的包正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值