XML

JavaWeb 专栏收录该内容
7 篇文章 0 订阅

XML简介

  • XML是指可扩展标记语言(eXtensible Markup Language),是一种标记语言,很类似HTML,它被设计的宗旨是传输数据,而非显示数据
  • XML标签没有被预定义,需要用户自定义标签
  • XML技术是W3C组织发布的

XML的应用

  1. 不同系统之间传输数据

  2. 用来表示生活中有关系的数据

  3. 经常用在配置文件中

XML的文档声明

  1. 创建文件的后缀名是.xml

  2. 如果要写一个xml文件,第一步必须要有文档声明,表示写的是xml文件
    <?xml version="1.0" encoding="gbk"?>,文档声明必须写在第一行第一列,version属性表示版本,有1.0和1.1,一般使用1.0,encoding属性表示编码,另一个属性standalone,表示是否需要依赖其他文件,若需要写standalone=“yes”,不需要standalone=“no”

XML的中文乱码问题解决

设置保存时候的编码方式和打开时的编码方式一致即可

XML元素(标签)的定义

  1. 标签定义有开始必须要有结束,<person></person>

  2. 如果标签没有内容,可以在标签内结束,如:<person/>

  3. 标签可以嵌套,如:<a><b></b></a>

  4. 一个xml文件中必须要有且仅有一个根标签,其它的标签都是这个标签下的标签

  5. 对于xml标签中出现的所有空格和换行,xml解析程序都会当做标签内容来处理

  6. xml中标签的命名规则
    (1)xml代码区分大小写
    (2)标签名称不能以数字或_开头
    (3)xml的标签不能以XML、xml、Xml等开头
    (4)标签不能包含空格和冒号
    (5)xml的标签可以是中文

XML中属性的定义

xml是标记型文档,可以有属性,如:<person id="aaa"></person>
属性定义的要求:

  1. 一个标签上可以有多个属性

  2. 属性值要用引号(单引号或双引号)引起来

  3. 属性名称的命名规范与标签名称的命名规范一样

xml的注释

<!--这是注释-->,xml中注释不能嵌套

xml的特殊字符

需要对特殊字符进行转义才能正常显示,如要显示a<b,可以写成a&lt;b,>用&gt;转义,双引号用&quot;转义,单引号用&apos;转义

xml的CDATA区

如果有多个字符都需要转义,可以把它们整体放到CDATA区里,就不需要转义了
写法:<![CDATA[内容]]>

xml的PI指令(处理指令)

作用:用来指挥软件如何解析xml文件,可以设置样式(一般没啥用)
xml-stylesheet指令:<?xml-stylesheet type="text/css" href="#"?>,只能对英文标签名称起作用

xml的约束简介

比如现在定义一个person的xml文件,只想要在这个文件里面保存人的相关信息,但是在xml文件中写了一个<猫>标签,虽然可以正常显示,但它不是人的信息,这时需要技术来规定xml中只能出现的元素,这就是约束。xml中的约束技术:dtd约束、schema约束

  1. dtd快速入门(能看懂就行)
    (1)创建dtd文件,后缀名为.dtd
    (2)xml文件中有几个元素,就在dtd文件中写几个<!ELEMENT>
    (3)复杂元素(有子元素)写法:<!ELEMENT 元素名称 (子元素1,子元素2)>
    (4)简单元素(无子元素)写法:<!ELEMENT 元素名称 (#PCDATA)>
    (5)在xml文件中引入dtd文件,<!DOCTYPE 根元素名称 SYSTEM "dtd文件的路径">
    (6)用浏览器打开xml文件,浏览器只校验语法,不校验约束,需要使用工具来校验约束

  2. dtd的引入方式
    (1)引入外部dtd文件,<!DOCTYPE 根元素名称 SYSTEM "dtd文件路径">
    (2)使用内部dtd文件

		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE person [
			<!ELEMENT person (name,age)>
			<!ELEMENT name (#PCDATA)>
			<!ELEMENT age (#PCDATA)>
		]>
		<person>
			<name>zhangsan</name>
			<age>20</age>
		</person>

(3)从公共网络上引入dtd文档,<!DOCTYPE 根元素名称 PUBLIC "dtd名称" "dtd文档的url">

  1. 在dtd文档中使用ELEMENT关键字来声明一个XML元素
    (1)语法:<!ELEMENT 元素名 使用规则>
    (2)简单元素约束例如:<!ELEMENT name (#PCDATA)>,其中, (#PCDATA)约束name是字符串类型,若为EMPTY,则约束<name></name>中内容为空,若为ANY,则可空也可不空
    (3)复杂元素约束如:<!ELEMENT person (name,age)>
    表示子元素出现的次数:若写成name+,表示name可以出现一次或多次;若写成age?,表示age可以出现0次或1次;若写成name*,表示name可以出现0次或1次或多次。在<!ELEMENT person (name,age)>中元素之间用逗号隔开,并且有顺序,若用 | 隔开,则表示这些子元素只能出现其中的任意一个

  2. 使用dtd定义属性
    语法:

	<!ATTLIST 元素名称
			属性1名称 属性类型 属性的约束
			属性2名称 属性类型 属性的约束
	>

属性类型:
CDATA:表示属性的取值为普通的文本字符串
枚举:只能从枚举列表中任选其一,如(鸡肉|牛肉|鱼肉)
ID:表示属性的取值不能重复,属性的值只能由字母、下划线开头,不能出现空白字符
属性约束设置说明:
#REQUIRED:表示该属性必须出现
#IMPLIED:表示该属性可有可无
#FIXED:表示属性的取值为一个固定值,语法:#FIXED "固定值"
直接值:表示属性的取值为该默认值,若不写属性,则使用直接值,若写属性,则使用设置的那个值

  1. 定义实体
    概念:在dtd中定义,在xml中使用
    语法:<!ENTITY 实体名称 "实体内容">
    引用方式:&实体名称;
    如在dtd中定义:<!ENTITY test "haha">
    在xml中使用:<name>&test;</name>
    注意:定义实体一般写在内部dtd中,如果写在外部dtd里面,在某些浏览器下,内容得不到

xml的解析的简介

  1. js使用dom解析HTML文档:根据HTML的层级结构,在内存中分配一个树形结构,把HTML的标签、属性和文本都封装成对象,有document对象、属性对象、文本对象、Node节点对象等

  2. xml的解析方式(技术):dom和sax
    (1)使用dom方式解析xml时,如果文件过大,会造成内存溢出,但可以很方便的实现增删改操作
    (2)sax解析过程:采用事件驱动,边读边解析(一行一行地解析,解析到某一个对象,把对象名称返回)。这种解析方式不会造成内存溢出,可以方便实现查询,但不能实现增删改操作

  3. 想要解析xml,首先需要解析器,不同的公司和组织提供了针对dom和sax方式的解析器,通过api的方式提供。如sun公司的jaxp,dom4j组织的dom4j(实际开发中使用最多),jdom组织的jdom

jaxp的api的查看

  • JAXP:(Java API for XML Processing)开发包是JavaSE的一部分,它由以下几个包及其子包组成
    org.w3c.dom:提供DOM方式解析XML的标准接口
    org.xml.sax:提供SAX方式解析XML的标准接口
    javax.xml:提供了解析XML文档的类

  • javax.xml.parsers包中,定义了几个工厂类,我们可以通过调用这些工厂类,得到对XML文档进行解析的DOM和SAX解析器对象
    (1)针对dom:DocumentBuilder(解析器类)、DocumentBuilderFactory(解析器工厂)
    DocumentBuilder:这是个抽象类,不能new,此类的实例可以从DocumentBuilderFactory.newDocumentBuilder()方法获取。这里面有一个方法parse(“xml的路径”)可以解析xml,返回的是Document整个文档,Document是个接口,其父接口是Node,如果在Document里面找不到想要的方法,可以到Node中去找。在Document中有个方法getElementByTagName(String tagname),这个方法可以得到标签,返回集合NodeList,还有创建标签的方法createElement(String tagname),创建文本的方法createTextNode(String data),Node里面有appendChild(Node newChild)方法可以添加节点
    DocumentBuilderFactory:这也是个抽象类,不能new,newInstance()方法获取实例
    (2)针对sax:SAXParser(解析器类)、SAXParserFactory(解析器工厂)

使用jaxp查询节点

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<p1>
		<name>zhangsan</name>
		<age>20</age>
	</p1>
	<p1>
		<name>lisi</name>
		<age>25</age>
	</p1>
</person>

需求:查询xml中所有的name元素的值

package packagetest;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class classtest {

	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
		//查询所有name元素的值
		/* 1、创建解析器工厂
		 * 2、根据解析器工厂创建解析器
		 * 3、解析xml返回Document
		 * 4、得到所有的name元素
		 * 5、返回集合,遍历集合,得到每一个name元素
		 * 
		 */
		DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();  //创建解析器工厂
		DocumentBuilder builder=builderFactory.newDocumentBuilder();   //创建解析器
		Document document=builder.parse("src/1.xml");  //解析xml返回Document
		NodeList list=document.getElementsByTagName("name");  //得到name元素
		for(int i=0;i<list.getLength();i++) {
			Node name1=list.item(i);    //得到每一个name元素
			String s=name1.getTextContent();     //得到标签里面的内容
			System.out.println(s);
		}

	}

}

在这里插入图片描述

使用jaxp查询某一个节点

若要获取第一个节点值,可使用代码

	Node name1=list.item(0);
	String s=name1.getTextContent();
	System.out.println(s);

使用jaxp添加节点

需求:在上面第一个<p1></p1>中添加一个sex

DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();  //创建解析器工厂
DocumentBuilder builder=builderFactory.newDocumentBuilder();   //创建解析器
Document document=builder.parse("src/1.xml");  //解析xml返回Document
NodeList list=document.getElementsByTagName("p1");  //得到所有的p1
Node p1=list.item(0);   //得到第一个p1
Element sex1=document.createElement("sex");   //创建标签
Text text1=document.createTextNode("nv");   //创建文本
sex1.appendChild(text1);   //把文本添加到sex1下面
p1.appendChild(p1);        //把sex1添加到p1下面
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/1.xml"));

使用jaxp修改节点

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<p1>
		<name>zhangsan</name>
		<age>20</age>
		<sex>nv</sex>
	</p1>
	<p1>
		<name>lisi</name>
		<age>25</age>
	</p1>
</person>

需求:修改nv为nan

  1. 创建解析器工厂

  2. 根据解析器工厂创建解析器

  3. 解析xml,返回Document

  4. 得到sex,使用item()方法

  5. 修改sex里面的值,setTextContent()方法

  6. 回写xml

DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();  //创建解析器工厂
DocumentBuilder builder=builderFactory.newDocumentBuilder();   //创建解析器
Document document=builder.parse("src/1.xml");  //解析xml返回Document
Node sex1=document.getElementsByTagName("sex").item(0);  //得到sex1
sex1.setTextContent("nan");  //修改sex的值
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/1.xml"));

使用jaxp删除节点

需求:删除上面的sex节点

  1. 创建解析器工厂

  2. 根据解析器工厂创建解析器

  3. 解析xml,返回Document

  4. 获取sex元素

  5. 获取sex的父节点

  6. 使用父节点删除,removeChild()方法

  7. 回写xml

DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();  //创建解析器工厂
DocumentBuilder builder=builderFactory.newDocumentBuilder();   //创建解析器
Document document=builder.parse("src/1.xml");  //解析xml返回Document
Node sex1=document.getElementsByTagName("sex").item(0);  //得到sex1
Node p1=sex1.getParentNode();  //得到父节点
p1.removeChild(sex1);
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/1.xml"));

jaxp遍历节点

需求:打印出所有标签的名称

  1. 创建解析器工厂

  2. 根据解析器工厂创建解析器

  3. 解析xml,返回Document

  4. 得到根节点及其子节点,使用递归实现

public static void main(String[] args) throws Exception {
		
		DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();  //创建解析器工厂
		DocumentBuilder builder=builderFactory.newDocumentBuilder();   //创建解析器
		Document document=builder.parse("src/1.xml");  //解析xml返回Document
		list1(document);
	}
	//递归遍历
	public 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++) {   //遍历list
			Node node1=list.item(i);    //得到每一个节点
			node1.getChildNodes();     //继续得到node1的子节点
			list1(node1);
		}
				
	}

在这里插入图片描述

schema约束

  1. XML Schema也是一种定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的局限性
    XML Schema vs DTD:
    (1)XML Schema符合XML语法结构
    (2)DOM、SAX等XML API很容易解析出XML Schema文档中的内容
    (3)XML Schema对名称空间支持得非常好
    (4)XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型
    (5)XML Schema定义约束的能力非常强大,可以对XML示例文档做出细致的语义限制
    (6)XML Schema不能像DTD一样定义实体,比DTD更复杂,但XML Schema现在已是w3c组织的标准,它正逐步替代DTD
    (7)一个xml中只能有一个dtd,但可以有多个schema,多个schema使用名称空间区分

  2. schema快速入门
    (1)XML Schema文件自身就是一个XML文件,但它的扩展名通常为.xsd。和XML一样,XML Schema文档必须也有一个根节点,但这个根节点的名称为Schema
    (2)编写了XML Schema约束文档之后,通常需要把这个文件中声明的元素绑定到一个URI地址上,这个URI地址叫namespace名称空间,以后XML文件就可以通过这个URI引用绑定指定名称空间的元素
    (3)在schema文件里面,xmlns="http://www.w3.org/2001/XMLSchema"属性表示当前文件是一个约束文件。targetNamespace="2019/4/17"引号里面的地址可以随便写,使用时通过这个地址引入约束文件。还有一个属性elementFormDefault="qualified"表示质量良好
    (4)在xml文件中有几个元素,在schema文件中就写几个元素,简单元素写在sequence里面,表示元素出现的顺序。下面分别是xml文件和schema文件

	<?xml version="1.0" encoding="UTF-8"?>
	<person>
		<name>zhangsan</name>
		<age>20</age>	
	</person>
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="2019/4/17"
elementFormDefault="qualified">
	<element name="person">
		<complexType>
			<sequence>    
				<element name="name" type="string"></element>
				<element name="age" type="int"></element>
			</sequence>
		</complexType>
	</element>
</schema>

(5)在xml文件中引入schema文件

<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="2019/4/17"
xsi:schemaLocation="2019/4/17 1.xsd">
	<name>zhangsan</name>
	<age>20</age>	
</person>

上面代码中,xmlns后面跟个:xsi表示给xmlns起个别名,xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"表示这是个被约束文件,上面的1.xsd处写约束文档的路径

schema约束的api的查看

  1. XML Schema复杂元素指示器
    All:表示只能出现一次
    Choice:只能出现其中一个
    Sequence:元素按照顺序出现
    maxOccurs="unbounded"指示元素出现次数,unbounded表示出现次数没有限制,<element name="name" type="double" maxOccurs="unbounded"/>
    <any></any>表示里面可以写任意元素

  2. schema里面定义属性(必须是复杂元素)
    写在</complexType>前面
    写法:<attribute name="id1" type="int" use="required></attribute>",name表示属性名称,type表示属性类型,use表示属性是否必须要出现(required表示属性必须要出现)

  3. 若要引入多个schema文件,可以给每个schema起一个别名,引用方式schema的别名:元素名称,如:<dept:name>100</dept:name>

sax的解析过程

事件驱动方式,边读边解析

  1. javax.xml.parsers包里面有两个类:SAXParser、SAXParserFactory
    SAXParser:此类的实例可以用SAXParserFactory.newSAXParser()方法得到。parse()方法的第一个参数为xml路径,第二个参数为事件处理器,当把事件处理器传递进来,相当于在方法里面绑定了一个事件
    SAXParserFactory:实例从newInstance()方法得到

  2. 比如有以下xml文件:

	<?xml version="1.0" encoding="UTF-8"?>
	<person>
		<name>zhangsan</name>
		<age>20</age>
	</person>

程序执行到<person><name>等这种开始标签的时候,会自动调用startElement(String uri,String localName,String qName,Attributes attributes)方法,该方法通过参数qName把标签名称返回,执行到文本zhangsan的时候自动调用characters(char[] ch,int start,int length)方法,返回文本内容,执行到</name>的时候自动调用endElement(String uri,String localName,String qName)方法

使用jaxp的sax方式解析xml

sax方式只能实现查询操作,不能实现增删改操作
来个需求:打印整个xml文档内容

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<p1>
		<name>zhangsan</name>
		<age>20</age>
	</p1>
	<p1>
		<name>lisi</name>
		<age>30</age>
	</p1>	
</person>

public class classtest {

	public static void main(String[] args) throws Exception {
		
		/*
		 * 1、创建解析器工厂
		 * 2、创建解析器
		 * 3、 执行parse方法
		 * 4、需要自己创建一个类,来继承DefaultHandler
		 * 5、重写类里面的三个方法
		 */
		SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();   //创建解析器工厂
		SAXParser saxParser=saxParserFactory.newSAXParser();   //创建解析器
		saxParser.parse("src/1.xml", new MyDefault1());   //执行parse方法
		
	}
	
}
class MyDefault1 extends DefaultHandler{

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		System.out.print("<"+qName+">");
	}
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		// TODO Auto-generated method stub
		super.characters(ch, start, length);
		System.out.print(new String(ch,start,length));
	}
	
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		System.out.print("<"+qName+"/>");
	}
}

在这里插入图片描述

再来个需求:打印所有name元素的值

public class classtest {

	public static void main(String[] args) throws Exception {
		
		/*
		 * 1、创建解析器工厂
		 * 2、创建解析器
		 * 3、 执行parse方法
		 * 4、需要自己创建一个类,来继承DefaultHandler
		 * 5、重写类里面的三个方法
		 */
		SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();   //创建解析器工厂
		SAXParser saxParser=saxParserFactory.newSAXParser();   //创建解析器
		saxParser.parse("src/1.xml", new MyDefault2());   //执行parse方法
	}
}
//实现获取所有name元素的值
class MyDefault2 extends DefaultHandler{
	
	boolean flag=false;
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		//判断qName是否是name元素
		if("name".equals(qName)) {
			flag=true;
		}
	}
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		// TODO Auto-generated method stub
		super.characters(ch, start, length);
		//当flag值是true的时候,表示解析到name元素
		if(flag==true) {
			System.out.println(new String(ch,start,length));
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		//把flag设置成false,表示name元素结束
		if("name".equals(qName)) {
			flag=false;
		}
	}
}

在这里插入图片描述

解析器dom4j简介

  1. dom4j不是javase的一部分,想要使用,需要导入dom4j提供的jar包。方法:创建一个文件夹lib,复制jar包到lib下面,右键点击lib,build path->add to build path(看到jar包变成奶瓶样子,即成功导入)

  2. 执行下面两行代码即可得到document文档

	SAXReader reader=new SAXReader();
	Document document=reader.read(url);

Document的父接口是Node,如果在Document里面找不到想要的方法,到Node里面去找

使用dom4j实现查询操作

来个需求:查询所有name元素里面的值

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<p1>
		<name>zhangsan</name>
		<age>20</age>
	</p1>
	<p1>
		<name>lisi</name>
		<age>30</age>
	</p1>	
</person>

public class classtest1 {

	public static void main(String[] args) throws Exception {
		/*
		 * 1、创建解析器				SAXReader reader=new SAXReader();									Document document=reader.read(url);
		 * 2、得到document			Document document=reader.read(url);
		 * 3、得到根节点				getRootElement()
		 * 4、得到所有的p1
		 * 			element(qname),表示获取标签下面的第一个子标签,qname即标签的名称,如name
		 * 			elements(qname),获取标签下面是qname这个名称的所有子标签(一层)
		 * 			elements(),获取标签下面的一层子标签
		 * 5、得到name
		 * 6、得到name里面的值
		 */
		selectName();

	}
	//查询xml中所有name元素的值
	public static void selectName() throws Exception{
		SAXReader reader=new SAXReader();   //创建解析器
		Document document=reader.read("src/1.xml");   //得到document
		Element root=document.getRootElement();   //得到根节点
		List<Element> list=root.elements("p1");   //得到p1
		//若想得到第二个p1,可用句子:Element p2=list.get(1);
		for(Element element:list) {
			//element是每一个p1元素
			//得到p1下面的name元素
			Element name1=element.element("name");
			//得到name里面的值
			String s=name1.getText();
			System.out.println(s);
		}
	}

}

使用dom4j实现添加操作

需求:在第一个p1下添加一个<sex>nv</sex>

//在第一个p1下添加一个<sex>nv</sex>
	public static void addSex() throws Exception {
		SAXReader reader=new SAXReader();   //创建解析器
		Document document=reader.read("src/1.xml");   //得到document
		Element root=document.getRootElement();   //得到根节点
		Element p1=root.element("p1");   //得到第一个p1
		Element sex1=p1.addElement("sex");  //直接添加sex
		sex1.setText("nv");   //在sex下添加文本
		//回写xml
		OutputFormat format=OutputFormat.createPrettyPrint();
		XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/1.xml"), format);
		xmlWriter.write(document);
		xmlWriter.close();   //关掉流
	}

使用dom4j在特点位置添加节点

需求:在第一个p1下面的age之前添加一个school

//在第一个p1下面的age之前添加一个school
	public static void addBeforeAge() throws Exception{
		SAXReader reader=new SAXReader();   //创建解析器
		Document document=reader.read("src/1.xml");   //得到document
		Element root=document.getRootElement();   //得到根节点
		Element p1=root.element("p1");   //得到第一个p1
		List<Element> list=p1.elements();  //得到第一个p1下面的所有元素
		Element school=DocumentHelper.createElement("school");    //创建要添加的元素
		school.setText("ligong");   //创建文本
		list.add(1, school);   //在特定位置添加
		//回写xml
		OutputFormat format=OutputFormat.createPrettyPrint();
		XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/1.xml"), format);
		xmlWriter.write(document);
		xmlWriter.close();   //关掉流
		
	}

dom4j里面封装方法

下面封装获取document方法和回写方法:

//工具类
class Dom4jUtils{
	public static Document getDocument(String path){
		//返回document
		try {
			SAXReader reader=new SAXReader();  //创建解析器
			Document document=reader.read(path);  //得到document
			return document;
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public static void xmlWriters(String path,Document document) {
		//回写xml
		try {
		OutputFormat format=OutputFormat.createPrettyPrint();
		XMLWriter xmlWriter=new XMLWriter(new FileOutputStream(path), format);
		xmlWriter.write(document);
		xmlWriter.close();   //关掉流
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

也可以把里面用到的xml文件的路径封装成一个常量,如:
public static final String PATH="src/1.xml";

使用dom4j实现修改节点

需求:修改第一个p1下的age元素的值为21

//修改第一个p1下的age元素的值为21
	public static void chAge() throws Exception{
		Document document=Dom4jUtils.getDocument("src/1.xml");  //用封装好的方法获取document
		Element root=document.getRootElement();   //得到根节点
		Element p1=root.element("p1");   //得到第一个p1
		Element age=p1.element("age");   //得到第一个p1下的age
		age.setText("21");    //修改age
		Dom4jUtils.xmlWriters("src/1.xml", document);   //用封装好的方法回写xml
	}

使用dom4j实现删除节点操作

需求:删除第一个p1下面的school

//删除第一个p1下的school
	public static void delSchool() throws Exception{
		Document document=Dom4jUtils.getDocument("src/1.xml");  //用封装好的方法获取document
		Element root=document.getRootElement();   //得到根节点
		Element p1=root.element("p1");   //得到第一个p1
		Element sch=p1.element("school");   //得到school
		p1.remove(sch);   //通过父节点删除
		Dom4jUtils.xmlWriters("src/1.xml", document);   //用封装好的方法回写xml

	}

使用dom4j实现获取属性值的操作

需求:获取第一个p1里面属性id1的值

<?xml version="1.0" encoding="UTF-8"?>
<person> 
  <p1 id1="aaa"> 
    <name>zhangsan</name>  
    <age>21</age>  
    <sex>nv</sex> 
  </p1>  
  <p1> 
    <name>lisi</name>  
    <age>30</age> 
  </p1> 
</person>

//获取第一个p1里面属性id1的值
	public static void getId() {
		Document document=Dom4jUtils.getDocument("src/1.xml");  //用封装好的方法获取document
		Element root=document.getRootElement();   //得到根节点
		Element p1=root.element("p1");   //得到第一个p1
		String id=p1.attributeValue("id1");
		System.out.println(id);
	}

在这里插入图片描述

XPATH的简介

学会看xpath文档

使用dom4j支持xpath操作

  1. 默认情况下,dom4j不支持xpath,如果想要在dom4j里面使用xpath,首先要引入支持xpath的jar包,把jar包导入到项目中

  2. dom4j里面提供了两个方法,用来支持xpath:selectNodes(“xpath表达式”)获取多个节点;selectSingleNode(“xpath表达式”)获取一个节点

来个需求:使用xpath查询xml中所有name元素的值

public static void seName() throws Exception{
		//查询xml中所有name元素的值
		SAXReader reader=new SAXReader();  //创建解析器
		Document document=reader.read("src/1.xml");  //得到document
		List<Node> list=document.selectNodes("//name");   //使用方法得到所有name元素
		//遍历list集合
		for(Node node:list) {
			String s=node.getText();   //node是每一个name元素,得到name元素里面的值
			System.out.println(s);
		}
	}
  • 2
    点赞
  • 0
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页

打赏作者

crossroadsss

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值