javaweb-day02-3(XML 解析 - Dom4j解析开发包 - XPath)

本文介绍了如何结合Dom4j API和XPath表达式方便地获取XML节点,并提供了XPath快速入门指南。通过示例展示了如何利用XPath选择多个和单个节点。还涉及到学生成绩管理系统重构的实践,包括需求分析、模块流程和开发顺序,强调了代码组织结构的重要性。

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

由于dom4j在获取某个节点时都得一级一级往下获,很不方便。

由于XPath表达式,获取某个节点很方便直观,所以就要由dom4j API 结合XPath表达式来获取节点,然后对节点进行某些操作。

 

  •   XPath快速入门,查看官方帮助文档:XPathTutorial.chm
  •   dom4j API 与XPath的结合,要看dom4j的docs里面的Quick Start:Powerful Navigation with XPath
    •   获取多个节点:Listlist = document. selectNodes ("//foo/bar");
    •   获取单个节点:Nodenode = document. selectSingleNode ("//foo/bar/author");

 

创建XPath需要jaxen.jar包的支持。如没有导入可能会报错:java.lang.NoClassDefFoundError: org/jaxen/JaxenException


练习一: 

book.xml

<?xml version="1.0" encoding="UTF-8"?>

<书架> 
  <书 name="yyyYYY"> 
    <书名>Java就业培训教程</书名>  
    <售价>999</售价>  
    <售价>999</售价>  
    <作者>张孝祥</作者>  
    <售价>20元</售价>  
    <售价>20元</售价>
  </书>  
  <书> 
    <书名>JavaScript网页开发</书名>  
    <作者>张孝祥</作者>  
    <售价>28.00元</售价> 
  </书> 
</书架>


//获取第二个书名的值

	@Test
	public void findwithXpath() throws DocumentException{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/book.xml");
		
		//获取第二个书名的值
		Element ele = (Element)document.selectNodes("//书名").get(1);
		System.out.println(ele.getText());
	}


练习二:

users.xml

<?xml version="1.0" encoding="UTF-8"?>

<users>
	<user username="lisi" password="123"></user>
	<user username="wanghong" password="123"></user>
	<user username="hehe" password="123"></user>
</users>

//用户登录

	@Test
	public void login() throws DocumentException{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/users.xml");
		
		String username = "lisi";
		String password = "123";
		
		Node node = document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");
		if(node != null){
			System.out.println("登录成功!");
		}else{
			System.out.println("用户名或密码错误......");
		}
		
	}


练习三:用dom4j做学生成绩管理系统的重构

需求分析:

1、以如下格式的exam.xml文件为例

exam.xml

<?xml version="1.0" encoding="UTF-8"?>

<exam> 
  <student examid="222" idcard="111"> 
    <name>张三</name>  
    <location>沈阳</location>  
    <grade>89.00</grade> 
  </student>  
  <student examid="444" idcard="333"> 
    <name>李四</name>  
    <location>大连</location>  
    <grade>97.00</grade> 
  </student> 
</exam>

2、编程实现如下功能


3、实现学生信息的添加


4、实现学生信息的查询


5、实现学生的删除功能


模块流程图:

添加数据:


查询数据:



开发顺序:

先写javabean,再写Dao用到的工具类、 Dao ,最后写界面层Main。

 

不同模块的程序,要放在不同的包里:

  •   实体javabean:放在domain包。
  •   Dao:放在dao包。dao操作xml文档必定会有重复代码:得到document、更新xml文档。将他们抽取到工具类XmlUtils里。
  •   工具类XmlUtils:放在utils工具包中。
  •   界面Main:放在main包。

 

程序源码:

package cn.mengmei.domain;

public class Student {
	private String idcard;
	private String examid;
	private String name;
	private String location;
	private double grade;
	
	public String getIdcard() {
		return idcard;
	}
	public void setIdcard(String idcard) {
		this.idcard = idcard;
	}
	public String getExamid() {
		return examid;
	}
	public void setExamid(String examid) {
		this.examid = examid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLocation() {
		return location;
	}
	public void setLocation(String location) {
		this.location = location;
	}
	public double getGrade() {
		return grade;
	}
	public void setGrade(double grade) {
		this.grade = grade;
	}
}

package cn.mengmei.utils;

import java.io.FileOutputStream;
import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class XMLUtils {
	
	public static Document getDocument() throws DocumentException{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/exam.xml");
		return document;
	}
	
	public static void write2XML(Document document) throws IOException{
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("UTF-8");
		XMLWriter writer = new XMLWriter(new FileOutputStream("src/exam.xml"),format);
		writer.write(document);
		writer.close();
	}
	
}

package cn.mengmei.dao;

import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;

import cn.mengmei.domain.Student;
import cn.mengmei.utils.XMLUtils;

public class StudentDao {

	public void add(Student student){
		try {
			Document document = XMLUtils.getDocument();
			Element root = document.getRootElement();
			
			Element stuNode = root.addElement("student");
			stuNode.addAttribute("idcard", student.getIdcard());
			stuNode.addAttribute("examid", student.getExamid());
			stuNode.addElement("name").setText(student.getName());
			stuNode.addElement("location").setText(student.getLocation());
			stuNode.addElement("grade").setText(student.getGrade()+"");
			
			XMLUtils.write2XML(document);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public void delete(String name){
		try {
			Document document = XMLUtils.getDocument();
			List<Node> nameList = document.selectNodes("//name");
			
			for(Iterator<Node> it=nameList.iterator(); it.hasNext(); ){
				Node nameNode = it.next();
				if(nameNode.getText().equals(name)){
					Node stuNode = nameNode.getParent();
					stuNode.getParent().remove(stuNode);
					XMLUtils.write2XML(document);
					return;
				}
			}
			throw new RuntimeException("------对不起,没有查到此学生!-----");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public Student read(String examid){
		
		try{
			Document document = XMLUtils.getDocument();
			
			Element stuNode = (Element)document.selectSingleNode("//student[@examid='"+examid+"']");
			if(stuNode != null){
				Student student = new Student();
				student.setIdcard(stuNode.attributeValue("idcard"));
				student.setExamid(stuNode.attributeValue("examid"));
				student.setName(stuNode.elementText("name"));
				student.setLocation(stuNode.elementText("location"));
				student.setGrade(Double.parseDouble(stuNode.elementText("grade")));
				return student;
			}
			return null;
			
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
}

package cn.mengmei.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import cn.mengmei.dao.StudentDao;
import cn.mengmei.domain.Student;

public class Main {

	public static void main(String[] args) {

		System.out.println("添加用户:(a)       删除用户:(b)       查询成绩:(c)");
		System.out.print("请输入操作类型:");
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String item = null;
		try {
			item = reader.readLine();
		} catch (IOException e) {
			System.out.println("-----------类型读取失败!---------");
		}
		
		Student student = null;
		String idcard = null;
		String examid = null;
		String name = null;
		String location = null;
		String grade = null;
		StudentDao dao = null;
		
		switch (item) {
		
		case "a":
			try{
				System.out.print("请输入学生姓名:");
				name = reader.readLine();
				System.out.print("请输入学生身份证号:");
				idcard = reader.readLine();
				System.out.print("请输入学生准考证号:");
				examid = reader.readLine();
				System.out.print("请输入学生所在地:");
				location = reader.readLine();
				System.out.print("请输入学生成绩:");
				grade = reader.readLine();
				
				student = new Student();
				student.setName(name);
				student.setIdcard(idcard);
				student.setExamid(examid);
				student.setLocation(location);
				student.setGrade(Double.parseDouble(grade));
				
				dao = new StudentDao();
				dao.add(student);
				
				System.out.println("--------添加数据成功--------");
			}catch(Exception e){
				System.out.println("---------对不起,添加失败!---------");
			}
			break;
			
		case "b":
			try{
				System.out.print("请输入要删除的学生姓名:");
				name = reader.readLine();
				dao = new StudentDao();
				dao.delete(name);
				System.out.println("------已成功删除学生信息------");
			}catch(Exception e){
				System.out.println(e.getMessage());
			}
			break;
			
		case "c":
			try {
				System.out.print("请输入要查询的学生准考证号:");
				examid = reader.readLine();
				dao = new StudentDao();
				student = dao.read(examid);
				if(student != null){
					System.out.println("姓名:"+student.getName());
					System.out.println("身份证号:"+student.getIdcard());
					System.out.println("准考证号:"+student.getExamid());
					System.out.println("所在地:"+student.getLocation());
					System.out.println("成绩:"+student.getGrade());
				}else{
					System.out.println("-----对不起,你要查询的学生信息不存在!-----");
				}
			} catch (Exception e) {
				System.out.println("------对不起,查询失败!------");
			}
			break;

		default:
			System.out.println("------对不起,不支持此种操作类型!------");
			break;
		}
	}

}






JsoupXpath 是一款纯Java开发的使用xpath解析html的解析器,xpath语法分析与执行完全独立,html的DOM树生成借助Jsoup,故命名为JsoupXpath.为了在java里也享受xpath的强大与方便但又苦于找不到一款足够强大的xpath解析器,故开发了JsoupXpath。JsoupXpath的实现逻辑清晰,扩展方便,支持几乎全部常用的xpath语法.http://www.cnblogs.com/ 为例 "//a/@href"; "//div[@id=&#39;paging_block&#39;]/div/a[text()=&#39;Next >&#39;]/@href"; "//div[@id=&#39;paging_block&#39;]/div/a[text()*=&#39;Next&#39;]/@href"; "//h1/text()"; "//h1/allText()"; "//h1//text()"; "//div/a"; "//div[@id=&#39;post_list&#39;]/div[position()1000]/div/h3/allText()"; //轴支持 "//div[@id=&#39;post_list&#39;]/div[self::div/div/div/span[@class=&#39;article_view&#39;]/a/num()>1000]/div/h3/allText()"; "//div[@id=&#39;post_list&#39;]/div[2]/div/p/preceding-sibling::h3/allText()"; "//div[@id=&#39;post_list&#39;]/div[2]/div/p/preceding-sibling::h3/allText()|//div[@id=&#39;post_list&#39;]/div[1]/div/h3/allText()"; 在这里暂不列出框架间的对比了,但我相信,你们用了会发现JsoupXpath就是目前市面上最强大的的Xpath解析器。 快速开始 如果不方便使用maven,可以直接使用lib下的依赖包跑起来试试,如方便可直接使用如下dependency(已经上传至中央maven库,最新版本0.1.1):    cn.wanghaomiao    JsoupXpath    0.1.1 依赖配置好后,就可以使用如下例子进行体验了!String xpath="//div[@id=&#39;post_list&#39;]/div[./div/div/span[@class=&#39;article_view&#39;]/a/num()>1000]/div/h3/allText()";String doc = "..."; JXDocument jxDocument = new JXDocument(doc); List<Object> rs = jxDocument.sel(xpath); for (Object o:rs){     if (o instanceof Element){             int index = ((Element) o).siblingIndex();             System.out.println(index);     }     System.out.println(o.toString()); } 其他可以参考 cn.wanghaomiao.example包下的例子 语法 支持标准xpath语法(支持谓语嵌套),支持全部常用函数,支持全部常用轴,去掉了一些标准里面华而不实的函数和轴,下面会具体介绍。语法可以参考http://www.w3school.com.cn/xpath/index.asp 关于使用Xpath的一些注意事项 非常不建议直接粘贴Firefox或chrome里生成的Xpa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值