XML编程
XML编程(CURD)
C:create 创建
R:retrieve 读取
U:update 更新
D:delete 删除
XML解析技术概述
- XML解析方式分为两种:DOM(Document Object Model)方式和SAX(Simple API for XML)方式。
DOM和SAX只是定义了一些接口,以及某些接口的缺省实现,而这个缺省实现只是用空方法来实现接口。一个应用程序如果需要DOM或SAX来访问XML文档,还需要一个实现了DOM或SAX的解析器,也就是说这个解析器需要实现DOM或SAX中定义的接口。提供DOM或SAX中定义的功能。- DOM: Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
使用DOM要求解析器把整个XML文档装载到一个Document对象中。Document对象包含文档元素,即根元素,根元素包含N多个子元素…
一个XML文档解析后对应一个Document对象,这说明使用DOM解析XML文档方便使用,因为元素与元素之间还保存着结构关系。
优先:使用DOM,XML文档的结构在内存中依然清晰。元素与元素之间的关系保留了下来!
缺点:如果XML文档过大,那么把整个XML文档装载进内存,可能会出现内存溢出的现象! - SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
DOM会一行一行的读取XML文档,最终会把XML文档所有数据存放到Document对象中。SAX也是一行一行的读取XML文档,但是当XML文档读取结束后,SAX不会保存任何数据,同时整个解析XML文档的工作也就结束了。
但是,SAX在读取一行XML文档数据后,就会给感兴趣的用户一个通知!例如当SAX读取到一个元素的开始时,会通知用户当前解析到一个元素的开始标签。而用户可以在整个解析的过程中完成自己的业务逻辑,当SAX解析结束,不会保存任何XML文档的数据。
优先:使用SAX,不会占用大量内存来保存XML文档数据,效率也高。
缺点:当解析到一个元素时,上一个元素的信息已经丢弃,也就是说没有保存元素与元素之间的结构关系,这也大大限制了SAX的使用范围。如果只是想查询XML文档中的数据,那么使用SAX是最佳选择!
- DOM: Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
想要解析XML,首先需要解析器,不同的公司和组织提供了针对dom和sax方式的解析器,通过api方式提供:
JAXP
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解析器对象。
- DocumentBuilderFactory
- SAXParserFactory
JAXP的API的查看
- jaxp是javase的一部分
- jaxp解析器在jdk的javax.xml.parsers包里面
四个类:分别是针对dom和sax解析使用的类
使用JAXP进行DOM解析
javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
获得JAXP中的DOM解析器
- 调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。
- 调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。
- 调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,进行可以利用DOM特性对整个XML文档进行操作了。
DOM模型(document object model):
- DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
- 在dom中,节点之间关系如下:
- 位于一个节点之上的节点是该节点的父节点(parent)
- 一个节点之下的节点是该节点的子节点(children)
- 同一层次,具有相同父节点的节点是兄弟节点(sibling)
- 一个节点的下一个层次的节点集合是节点后代(descendant)
- 父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
Node对象:
常用方法
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()
- 得到标签里面的内容
查询节点
要求:查询xml中所有的name元素的值
步骤:
- 创建解析器工厂
DocumentBuilderFactory.newInstance(); - 根据解析器工厂创建解析器
builderFactory.newDocumentBuilder(); - 解析xml返回document
Document document = builder.parse(“src/person.xml”); - 到所有的name元素
使用document.getElementsByTagName(“name”); - 返回集合,遍历集合,得到每一个name元素
遍历 getLength() item()
得到元素里面值 使用 getTextContent()
import org.w3c.dom.*;
import javax.xml.parsers.*;
class Demo
{
public static void main(String[] args)throws Exception{
//创建解析器工厂
DocumentBuilderFactory builderFactory =DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//获得Docuemnt对象
Document document =builder.parse("person.xml");
//遍历集合
NodeList list=document.getElementsByTagName("name");
for(int i=0;i<list.getLength();i++){
Node name1=list.item(i);
System.out.println(name1.getTextContent());
}
}
}
运行结果:
通过以上方法我们我们获得的是所有name元素的内容,如果我们想获得第一个name元素的内容,可以用以下方式:取消for循环并将具体的参数传递:list.item(0);
添加节点
要求:继续上述步骤,在第一个p1下面(末尾)添加 <sex>nv</sex>
步骤:
1、创建解析器工厂
2、根据解析器工厂创建解析器
3、解析xml,返回document
4、得到第一个p1(先得到所有p1,再使用item(0)方法下标得到)
5、创建sex标签 createElement
6、创建文本 createTextNode
7、把文本添加到sex下面 appendChild
8、把sex添加到第一个p1下面 appendChild
9、回写xml
关于回写XML,是因为DOM在解析XML文档时根据xml的层级结构,将xml文档在内存当中分配成一个树形结构。把每个标签,属性,文本都封装成了一个对象。而前8个步骤都只是在内存中添加了一个节点,实际XML文件中并没有改变。所以需要回写XML,将内存中的内容重新写入到XML文件。
更新XML文档
- javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档。利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
- Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
- javax.xml.transform.dom.DOMSource类来关联要转换的document对象,
- 用javax.xml.transform.stream.StreamResult 对象来表示数据的目的地。
- Transformer对象通过TransformerFactory获得。
代码实现:
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
class Demo
{
public static void main(String[] args)throws Exception{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
//得到所有的p1
NodeList list = document.getElementsByTagName("p1");
//得到第一个p1
Node p1 = list.item(0);
//创建标签
Element sex1 = document.createElement("sex");
//创建文本
Text text1 = document.createTextNode("nv");
//把文本添加到sex1下面
sex1.appendChild(text1);
//把sex1添加到p1下面
p1.appendChild(sex1);
//回写xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
//将document 对象转换为 xml文件
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
}
结果:
文档中含有中文,设置编码格式写入的形式;设置回写xml格式化方式:
//设置格式化方式
OutputFormat format = OutputFormat.createPrettyPrint();// 指定XML编码
format.setEncoding(“utf-8");
XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);
writer.write(document);
writer.close();
修改节点
要求:继续上述操作,修改第一个p1下面的sex内容是nan(setTextContent)
package cn.itcast.jaxptest;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
class Demo
{
public static void main(String[] args)throws Exception{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
Node sex1=document.getElementsByTagName("sex").item(0);
sex1.setTextContent("nan");
//回写xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
}
结果:
删除节点
要求:继续上述操作,删除<sex>nan</sex>节点
要点:获取sex元素和sex元素的父节点,删除需要父节点调用删除方法(removeChild)
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
class Demo
{
public static void main(String[] args)throws Exception{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
Node sex1=document.getElementsByTagName("sex").item(0);
Node p1=sex1.getParentNode();
p1.removeChild(sex1);
//回写xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
}
结果:
遍历节点
要求:将XML中的所有元素名称打印出来
步骤:
1、创建解析器工厂
2、根据解析器工厂创建解析器
3、解析xml,返回document
↓使用递归实现↓
4、得到根节点
5、得到根节点子节点
6、得到根节点子节点的子节点
要点:除了要了解递归的性质以外,由于XML解析的特性,它会将空格、回车换行符一并解析为文本节点,即#TEXT。这样除了输出所有的元素名称以外,还多了许多#TEXT,所以我们需要事先判断节点类型是否属于Element(在Node类中有关于类型的变量)。
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
class Demo
{
public static void main(String[] args)throws Exception{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse("src/person.xml");
listElements(document);
}
private static void listElements(Node node) {
if (node.getNodeType()==Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
//得到一层子节点
NodeList nodeList=node.getChildNodes();
for (int i=0;i<nodeList.getLength();i++){
//得到每一个节点
Node node1=nodeList.item(i);
//继续得到node1的子节点
//node1.getChildNodes()
listElements(node1);
}
}
}
结果:
使用JAXP进行SAX解析
SAX解析方式会逐行地去扫描XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML (Simple API for XML) ,不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
优点是在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷。不需要加载进内存,因此不存在占用内存的问题,可以解析超大XML。缺点是只能用来读取XML中数据,无法进行增删改。
- SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
- 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
- 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
- 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
SAX的事件驱动模型
SAX解析原理
- SAX 是事件驱动的 XML 处理方法,它是基于事件驱动的
- 在javax.xml.parsers包里面:
-
SAXParser类
此类的实例可以从 SAXParserFactory.newSAXParser() 方法获得
parse(File f, DefaultHandler dh)
第一个参数:xml的路径
第二个参数:事件处理器 -
SAXParserFactory类:实例 newInstance() 方法得到
-
DefaultHandler类(在 org.xml.sax.helpers 软件包中)来实现所有这些回调,并提供所有回调方法默认的空实现
startElement() 回调在每次 SAX 解析器遇到元素的起始标记时被调用
characters() 回调为字符数据所调用
endElement() 为元素的结束标记所调用
注意:这些方法在默认情况下执行后什么都不会发生,所以需要创建子类继承该类并复写其中的方法。
-
示例:使用SAX解析XML并输出其中的内容
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class TestSax {
public static void main(String[] args) throws Exception {
/*
* 1、创建解析器工厂
* 2、创建解析器
* 3、执行parse方法
*
* 4、自己创建一个类,继承DefaultHandler
* 5、重写类里面的三个方法
* */
//创建解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//创建解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//执行parse方法
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 {
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+">");
}
}
结果:
dom4j
简介
- Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
- Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
- 使用Dom4j开发,需下载dom4j相应的jar文件。
DOM4J中的类结构
在DOM4J中,也有Node、Document、Element等接口,结构上与DOM中的接口比较相似。但还是有很多的区别:
在DOM4J中,所有XML组成部分都是一个Node,其中Branch表示可以包含子节点的节点,例如Document和Element都是可以有子节点的,它们都是Branch的子接口。
Attribute是属性节点,CharacterData是文本节点,文本节点有三个子接口,分别是CDATA、Text、Comment。
获取Document对象
DOM4j中,获得Document对象的方式有三种:
-
使用DOM4J来加载XML文档,需要先获取SAXReader对象,然后通过SAXReader对象的read()方法来加载XML文档:
SAXReader reader = new SAXReader(); //reader.setValidation(true); Document doc = reader.read("src/students.xml");
-
解析XML形式的文本,得到document对象.
String text = "<members></members>"; Document document = DocumentHelper.parseText(text);
-
主动创建document对象.
Document document = DocumentHelper.createDocument(); //创建根节点 Element root = document.addElement("members");
使用dom4j对XML进行操作
查询节点
要求:查询xml中所有name元素的值
xml:
实现:
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{
/*
* 1、创建解析器
* 2、得到document
* 3、得到根节点
*
* 4、得到p1
* 5、得到p1下面的name
* 6、得到name里面的值
* */
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Element root =document.getRootElement();
List<Element> element=root.elements("p1");
for(Element e:element){
Element name= e.element("name");
System.out.println(name.getText());
}
}
}
添加节点(有回写操作)
要求:在第一个p1下面的age标签之前添加 <school>ecit.edu.cn</schlool>
xml:
实现:
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{
//创建解析器
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Element root =document.getRootElement();
//获取第一个p1中的所有元素,并将创建好的school元素插入到指定位置的集合中
Element p1=root.element("p1");
List<Element> list=p1.elements();
Element school =DocumentHelper.createElement("school");
school.setText("qinghua");
list.add(1,school);
//回写xml
OutputFormat outputFormat=OutputFormat.createPrettyPrint();//xml输出的格式,带换行 createCompactFormat()不带换行,在一行中显示
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),outputFormat);
xmlWriter.write(document);
xmlWriter.close();//一定要关闭流
}
}
结果:
要点:
- 运用到了list集合的add方法
- dom4j的回写操作:用到了XMLWriter和OutputFormat类(非javase中的类)
OutputFormat表示用于格式化XML输出的格式配置
createCompactFormat():不带格式(写在一行)
createPrettyPrint() :带格式(带有空格和换行)
提示:默认生成XML文件排版格式比较乱,可以通过OutputFormat类格式化输出,默认采用createCompactFormat()显示比较紧凑,最好使用createPrettyPrint()。 - DocumentHelper:用于创建具体的元素对象
修改节点
要求:继续以上步骤,修改第一个p1下面的age元素的值 <age>30</age>,将年龄改为20
实现:
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{
//创建解析器
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Element root =document.getRootElement();
Element p1=root.element("p1");
Element age1=p1.element("age");
age1.setText("20");
//回写xml
OutputFormat outputFormat=OutputFormat.createPrettyPrint();//xml输出的格式,带换行 createCompactFormat()不带换行,在一行中显示
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),outputFormat);
xmlWriter.write(document);
}
}
要点:
- 用到了 setText(“文本内容”) 方法
删除节点
要求:删除第一个p1下面的<school>ecit</school>元素
实现:
package cn.itcast.dom4jtest;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{
//创建解析器
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Element root =document.getRootElement();
//获得父节点p1和要删除的子节点school,通过p1调用remove方法才能删除
Element p1=root.element("p1");
Element school=p1.element("school");
p1.remove(school);
//回写xml
OutputFormat outputFormat=OutputFormat.createPrettyPrint();//xml输出的格式,带换行 createCompactFormat()不带换行,在一行中显示
XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("src/p1.xml"),outputFormat);
xmlWriter.write(document);
}
}
要点:
- 要删除一个元素需要获得该元素的父元素再通过remove方法方可删除,因为元素不能自己删除自己。
获得属性
要求:获取第一个p1里面的属性id1的值
XML:
实现:
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class test{
public static void main(String[] args)throws Exception{//创建解析器
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Element root =document.getRootElement();
//获得属性值
Element p1=root.element("p1");
String value=p1.attributeValue("id1");
System.out.println(value);
}
}
结果:
要点:
- 获取属性值:String attributeValue(“属性名称”);
扩展:
-
设置某节点的属性和文字:
newMemberElm.addAttribute(“name”, “sitinspring”); -
设置属性的文字:
Attribute attribute=root.attribute(“name”);
attribute.setText(“sitinspring”);
XPATH
什么是XPATH?
XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初 XPath 的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是 XPath 很快的被开发者采用来当作小型查询语言。
XPATH语法
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
. . | 选取当前节点的父节点。 |
@ | 选取属性。 |
- 第一种形式
/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。如果想要在dom4j里面支持xpath的操作,需要引入支持xpath的jar包,把jar包导入到项目中。
- 在dom4j里面提供了两个方法,用来支持xpath:
selectNodes(“xpath表达式”): 获取多个节点
selectSingleNode(“xpath表达式”):获取一个节点
示例1:查询xml中所有name元素的值
XML:
实现:
package cn.itcast.dom4jtest;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{
//创建解析器获取Docuemnt对象
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
//获得所有name元素并返回集合
List<Node> list=document.selectNodes("//name");
for(Node node:list){
System.out.println(node.getText());
}
}
}
结果:
示例2:获取第一个p1下面的name的值
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import java.util.List;
public class test{
public static void main(String[] args)throws Exception{//创建解析器
SAXReader reader=new SAXReader();
Document document= reader.read("src/p1.xml");
Node p1=document.selectSingleNode("//p1[@id1='aaaa']/name");
System.out.println(p1.getText());
}
}
结果:
实现简单的学生管理系统
要求:使用xml当做数据,存储学生信息,实现增删查的操作
首先创建XML文件
<?xml version="1.0" encoding="UTF-8"?>
<sudent>
<stu>
<id>100</id>
<name>zhangsan</name>
<age>20</age>
</stu>
<stu>
<id>101</id>
<name>lisi</name>
<age>30</age>
</stu>
</sudent>
封装学生类:
public class Student {
private String id;
private String name;
private String age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
实现:
package cn.itcast.service;
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import cn.itcast.vo.Student;
public class StuService {
//查询 根据id查询学生信息
public static Student getStu(String id) throws Exception {
/*
* 1、创建解析器
* 2、得到document
*
* 3、获取到所有的id
* 4、返回的是list集合,遍历list集合
* 5、得到每一个id的节点
* 6、id节点的值
* 7、判断id的值和传递的id值是否相同
* 8、如果相同,先获取到id的父节点stu
* 9、通过stu获取到name age值
*
* */
//创建解析器
SAXReader saxReader = new SAXReader();
//得到document
Document document = saxReader.read("src/student.xml");
//获取所有的id
List<Node> list = document.selectNodes("//id");
//创建student对象
Student student = null;
//遍历list
for (Node node : list) { //node是每一个id节点
//得到id节点的值
String idv = node.getText();
//判断id是否相同
if(idv.equals(id)) {
//得到id的父节点 stu
Element stu = node.getParent();
//通过stu获取name和age
String namev = stu.element("name").getText();
String agev = stu.element("age").getText();
student.setId(idv);
student.setName(namev);
student.setAge(agev);
}
}
return student;
}
//增加
public static void addStu(Student student) throws Exception {
/*
* 1、创建解析器
* 2、得到document
* 3、获取到根节点
* 4、在根节点上面创建stu标签
* 5、在stu标签上面依次添加id name age
* 6、在id name age上面依次添加值
*
* 7、回写xml
* */
//创建解析器
SAXReader saxReader = new SAXReader();
//得到document
Document document = saxReader.read("src/student.xml");
//得到根节点
Element root = document.getRootElement();
//在根节点上面添加stu
Element stu = root.addElement("stu");
//在stu标签上面依次添加id name age标签
Element id1 = stu.addElement("id");
Element name1 = stu.addElement("name");
Element age1 = stu.addElement("age");
//在id name age上面依次添加值
id1.setText(student.getId());
name1.setText(student.getName());
age1.setText(student.getAge());
//回写xml
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
//删除 根据学生的id删除
public static void delStu(String id) throws Exception {
/*
* 1、创建解析器
* 2、得到document
*
* 3、获取到所有的id
* 使用xpath //id 返回 list集合
* 4、遍历list集合
* 5、判断集合里面的id和传递的id是否相同
* 6、如果相同,把id所在的stu删除
*
* */
//创建解析器
SAXReader saxReader = new SAXReader();
//得到document
Document document = saxReader.read("src/student.xml");
//获取所有的id xpath: //id
List<Node> list = document.selectNodes("//id");
//遍历list集合
for (Node node : list) { //node是每一个id的元素
//得到id的值
String idv = node.getText();
//判断idv和传递的id是否相同
if(idv.equals(id)) { //id相同
//得到stu节点
Element stu = node.getParent();
//获取stu的父节点
Element student = stu.getParent();
//删除stu
student.remove(stu);
}
}
//回写xml
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
}