JavaWeb学习笔记(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是最佳选择!

想要解析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元素的值
在这里插入图片描述

步骤:

  1. 创建解析器工厂
    DocumentBuilderFactory.newInstance();
  2. 根据解析器工厂创建解析器
    builderFactory.newDocumentBuilder();
  3. 解析xml返回document
    Document document = builder.parse(“src/person.xml”);
  4. 到所有的name元素
    使用document.getElementsByTagName(“name”);
  5. 返回集合,遍历集合,得到每一个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对象的方式有三种:

  1. 使用DOM4J来加载XML文档,需要先获取SAXReader对象,然后通过SAXReader对象的read()方法来加载XML文档:

    SAXReader reader = new SAXReader();
    //reader.setValidation(true);
    Document doc = reader.read("src/students.xml");
    
  2. 解析XML形式的文本,得到document对象.

    String text = "<members></members>";           
    Document document = DocumentHelper.parseText(text);
    
  3. 主动创建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();//一定要关闭流
    }
}

结果:
在这里插入图片描述
要点:

  1. 运用到了list集合的add方法
  2. dom4j的回写操作:用到了XMLWriter和OutputFormat类(非javase中的类)
    OutputFormat表示用于格式化XML输出的格式配置
    createCompactFormat():不带格式(写在一行)
    createPrettyPrint() :带格式(带有空格和换行)
    提示:默认生成XML文件排版格式比较乱,可以通过OutputFormat类格式化输出,默认采用createCompactFormat()显示比较紧凑,最好使用createPrettyPrint()。
  3. 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);
    }
}

要点:

  1. 用到了 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);
    }
}

要点:

  1. 要删除一个元素需要获得该元素的父元素再通过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);
    }
}

结果:
在这里插入图片描述
要点:

  1. 获取属性值: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();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值