JavaWeb-05
JavaWeb-XML基础(Dom解析和Sax解析)
一、XML的概述(了解)
- eXtensible Markup Language 可扩展标记语言
- 宗旨是传输数据,而非显示数据。
- XML标签没有被预定义,需要用户自行定义标签。
- XML技术是W3C组织(WorldWideWeConsortium万维网联盟)发布的,目前遵循的是W3C组织于2000年发布的XML1.0规范。
- 作用:
a. 传输数据 b. 配置文件(主要用途)
- XML技术用于解决什么问题?
a. XML语言出现的根本目的在于描述向上图那种有关系的数据。
b. XML是一种通用的数据交换格式。
c. 在XML语言中,它允许用户自定义标签。一个标签用于描述一段数据;一个标签可分为开始标签和结束标签,在起始标签之间,又可以使用其它标签描述其它数据,以此来实现数据关系的描述。
d. XML中的数据必须通过软件程序来解析执行或显示,如IE;这样的解析程序称之为Parser(解析器)。
- XML常见应用:
a. 在Java开发中,传统的配置文件是*.properties属性文件(key=value),而XML表示的数据更为丰富。 b. XML技术除用于描述有关系的数据外,还经常用作软件配置文件,以描述程序模块之间的关系。(如后面将要学习到的Struts、Spring和Hibernate都是基于XML作为配置文件的) c. 在一个软件系统中,通过XML配置文件可以提高系统的灵活性。即程序的行为是通过XML文件来配置的,而不是硬编码。
二、XML的语法(掌握)
1、<?xml version=“1.0”?> 文档声明必须出现在第一句
2、用encoding属性说明文档所使用的字符编码,默认为UTF-8。保存在磁盘上的文件编码要与声明的编码一致。
如:<?xml version=“1.0” encoding=“GB2312”?>
3、用standalone属性说明文档是否独立,即是否依赖其他文档。
如:<?xml version=“1.0” standalone=“yes”?>
4、一个标签有如下两种书写形式:
包含标签主体:<mytag>some content</mytag>
不含标签主体:<mytag/>
5、一个XML文档必须有且仅有一个根标签,但所有标签必须合理的嵌套,不允许有交叉嵌套。
如:<mytag1><mytag2></mytag1></mytag2> WRONG
6、XML中不会忽略主体内容中出现的空格和换行。
7、严格区分大小写
8、注释
<!--这是注释-->
9、CDATA : 把标签当做普通文本内容;
<![CDATA[
<itcast>www.itcast.cn</itcast>
]]>
Demo
<?xml version = "1.0" ?>
<!DOCTYPE 书架 SYSTEM "book.dtd">
<书架>
<书>
<书名>葵花宝典</书名>
<作者>陈冠希</作者>
<售价>100</售价>
</书>
<书>
<书名>金瓶梅</书名>
<作者>阿娇</作者>
<售价>80</售价>
</书>
</书架>
三、XML的约束(看懂即可,掌握引入外部约束文件的语句)
1、为什么需要约束和什么叫做约束?
XML都是用户自定义的标签,若出现小小的错误,软件程序将不能正确地获取文件中的内容而报错。(如:Tomcat)。XML技术中,可以编写一个文档来约束一个XML的书写规范,这个文档称之为约束。总之:约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等。
2、常见约束:XML DTD、XDR、SOX、XML Schema。
DTD:
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
3、分类:
格式良好的XML:遵循XML语法的XML
有效的XML:遵循约束文档的XML
约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等。
注意:dtd文档必须用utf-8编码格式保存
4、校验XML的有效性(如何根据DTD中定义的内容来验证XML书写是否正确呢?答:需要软件程序,即解析器)
非校验解析器:
<script type="text/javascript">
<!--
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.validateOnParse = "true" ;
xmldoc.load("book.xml");
var reason = xmldoc.parseError.reason;
var line = xmldoc.parseError.line ;
document.write(line + ":" + reason) ;
//-->
</script>
校验解析器
a. DTD 文件的引入:
当引用的DTD文档在本地时,采用如下方式:<!DOCTYPE 根元素 SYSTEM “DTD文档路径”>
当引用的DTD文档在公共网络上时,采用如下方式:
<!DOCTYPE 根元素 PUBLIC “DTD名称” “DTD文档的URL”>
eg : <!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
b. DTD文件的语法(定义元素、定义属性、定义实体)
在DTD文档中使用ELEMENT关键字来声明一个XML元素。
如果子元素用逗号分开,说明必须按照声明顺序去编写XML文档。
如果子元素用“|”分开,说明任选其一
用+、*、?来表示元素出现的次数
定义属性:
<!ATTLIST 元素名
属性名1 属性值类型 设置说明
属性名2 属性值类型 设置说明
…
>
例如:
<!ATTLIST 商品
类别 CDATA #REQUIRED
颜色 CDATA #IMPLIED
对应的XML为:<商品 类别=“服装” 颜=色=“黄色”/>
c. Schema(难)
四、XML的解析(掌握)
Java解析XML概述:XML解析方式分为两种:DOM方式和SAX方式
DOM:Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
XML解析开发包:
JAXP:是SUN公司推出的解析标准实现。
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
Dom4J:是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)
JDom:是开源组织推出的解析开发包。
解析的方式(使用JAXP)
1、DOM 解析(Java解析) : 利用DOM树来解析
book.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?><书架>
<书 ISBN="黑马程序员">
<书名>葵花宝典</书名>
<作者>陈冠希</作者>
<售价><会员价>50</会员价></售价>
<批发价>60</批发价>
<批发价>60</批发价><批发价>60</批发价></书>
<书>
<书名>金瓶梅</书名>
<作者>阿娇</作者>
<售价>70</售价>
</书>
</书架>
Book.java
public class Book {
private String bookName ;
private String author ;
private float price ;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString() {
return "Book [bookName=" + bookName + ", author=" + author + ", price="
+ price + "]";
}
}
DOM_parseXML.java
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;
//演示DOM方式解析XML文件
public class DOM_parseXML {
public static void main(String[] args) throws Exception {
//创建一个DOM解析器
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder() ;
//加载文档
Document document = db.parse("src/book.xml") ;
// test1(document) ;
test2(document) ;
// test3(document) ;
// test4(document) ;
// test5(document) ;
// test6(document) ;
// test7(document) ;
}
// 1、得到某个具体的节点内容 eg:获得金瓶梅的售价
public static void test1(Document document){
//获取售价节点的集合
NodeList nl = document.getElementsByTagName("售价") ;
//获取金瓶梅的售价节点
Node node = nl.item(1) ;
//拿到售价节点的主体内容
String price = node.getTextContent() ;
System.out.println(price);
}
// 2、遍历所有元素节点
public static void test2(Node node){
//先拿到node的节点的所有儿子
NodeList nl = node.getChildNodes() ;
//循环判断
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i) ;
if(n.getNodeType() == Node.ELEMENT_NODE){
//说明节点是标签节点
System.out.println(n.getNodeName());
test2(n) ;
}
}
}
// 3、修改某个元素节点的主体内容 eg:修改金瓶梅的价格为70
public static void test3(Document document) throws Exception{
//获取售价节点的集合
NodeList nl = document.getElementsByTagName("售价") ;
//获取金瓶梅的售价节点
Node node = nl.item(1) ;
//修改售价节点的主体内容
((Element)node).setTextContent("70") ;
//将结果写回到硬盘
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/book.xml")) ;
}
// 4、向指定元素节点中增加子元素节点 eg: 给葵花宝典的售价增加一个子节点: 会员价:50
public static void test4(Document document) throws Exception{
//获取售价节点的集合
NodeList nl = document.getElementsByTagName("售价") ;
//获取葵花宝典的售价节点
Node node = nl.item(0) ;
//创建一个新的标签节点: 会员价
Element el = document.createElement("会员价") ;
el.setTextContent("50") ;
//将会员价节点附加到葵花宝典节点后
node.appendChild(el) ;
//将结果写回到硬盘
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/book.xml")) ;
}
// 5、向指定元素节点上增加同级元素节点 eg: 给葵花宝典的售价增加一个兄弟节点: 批发价:60
public static void test5(Document document) throws Exception{
//获取书节点的集合
NodeList nl = document.getElementsByTagName("书") ;
//获取葵花宝典的书节点
Node node = nl.item(0) ;
//创建一个新的标签节点: 批发价
Element el = document.createElement("批发价") ;
el.setTextContent("60") ;
//将批发价节点附加到葵花宝典节点后
node.appendChild(el) ;
//将结果写回到硬盘
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/book.xml")) ;
}
// 6、删除指定元素节点 eg:删除会员价节点
public static void test6(Document document) throws Exception{
//获取售价节点的集合
NodeList nl = document.getElementsByTagName("售价") ;
//获取葵花宝典的售价节点
Node node = nl.item(0) ;
//获得会员价节点
Node hnode = node.getLastChild().getPreviousSibling() ;
System.out.println(hnode.getNodeName());
node.removeChild(hnode) ;
//将结果写回到硬盘
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/book.xml")) ;
}
// 7、操作XML文件属性 eg: 给葵花宝典的书节点增加属性: ISBN ="黑马程序员"
public static void test7(Document document) throws Exception{
//获取书节点的集合
NodeList nl = document.getElementsByTagName("书") ;
//获取葵花宝典的书节点
Node node = nl.item(0) ;
//增加属性
((Element)node).setAttribute("ISBN", "黑马程序员") ;
//将结果写回到硬盘
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/book.xml")) ;
}
}
2、SAX 解析 : 边加载边解析
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
Sax_parser1.java
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
//演示sax解析各个方法调用的时机
public class Sax_parser1 {
public static void main(String[] args) throws Exception {
//创建一个Sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser() ;
//获取XML文档的读取器
XMLReader reader = sax.getXMLReader() ;
//注册内容处理器
reader.setContentHandler(new DefaultHandler(){
//是在加载文档开始的时候执行
@Override
public void startDocument() throws SAXException {
System.out.println("文档解析开始了");
}
//文档解析结束时执行
@Override
public void endDocument() throws SAXException {
System.out.println("文档解析结束了");
}
//在读取到开始标签的时候执行
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
System.out.println("uri:"+uri+"、localName:"+localName+"、qName:"+qName + " 标签开始了、"+"attributes:"+attributes);
}
//是在读取到结束标签的时候执行
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("uri:"+uri+"、localName:"+localName+"、qName:"+qName +"解析结束了");
}
//读取到文本节点的时候执行
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println("文档内容: " + new String(ch,start,length));
}
}) ;
//加载文档
reader.parse("src/book.xml") ;
}
}
输出结果:
文档解析开始了
uri:、localName:、qName:书架 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容:
uri:、localName:、qName:书 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容:
uri:、localName:、qName:书名 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 葵花宝典
uri:、localName:、qName:书名解析结束了
文档内容:
uri:、localName:、qName:作者 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 陈冠希
uri:、localName:、qName:作者解析结束了
文档内容:
uri:、localName:、qName:售价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
uri:、localName:、qName:会员价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 50
uri:、localName:、qName:会员价解析结束了
uri:、localName:、qName:售价解析结束了
文档内容:
uri:、localName:、qName:批发价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 60
uri:、localName:、qName:批发价解析结束了
文档内容:
uri:、localName:、qName:批发价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 60
uri:、localName:、qName:批发价解析结束了
uri:、localName:、qName:批发价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 60
uri:、localName:、qName:批发价解析结束了
uri:、localName:、qName:书解析结束了
文档内容:
uri:、localName:、qName:书 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容:
uri:、localName:、qName:书名 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 金瓶梅
uri:、localName:、qName:书名解析结束了
文档内容:
uri:、localName:、qName:作者 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 阿娇
uri:、localName:、qName:作者解析结束了
文档内容:
uri:、localName:、qName:售价 标签开始了、attributes:com.sun.org.a[email protected]1db9742
文档内容: 70
uri:、localName:、qName:售价解析结束了
文档内容:
uri:、localName:、qName:书解析结束了
文档内容:
uri:、localName:、qName:书架解析结束了
文档解析结束了
Sax_parser2.java
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
//演示获取XML的数据 eg: 读取金瓶梅的作者: 阿娇
public class Sax_parser2 {
public static void main(String[] args) throws Exception {
//创建一个Sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser() ;
//获取XML文档的读取器
XMLReader reader = sax.getXMLReader() ;
//注册内容处理器
reader.setContentHandler(new DefaultHandler(){
int index = 0 ; //记录是第几个作者
String curName ; //记录当前标签的名字
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
if(qName.equals("作者")){
curName = "作者" ;
index++ ;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
curName = null ;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if("作者".equals(curName) && index == 2 ){
System.out.println(new String(ch,start,length));
}
}
}) ;
//加载文档
reader.parse("src/book.xml") ;
}
}
输出结果:阿娇
Sax_parser3.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.heima.bean.Book;
//演示将XML文档的数据包装成bean
public class Sax_parser3 {
public static void main(String[] args) throws Exception {
//创建一个Sax解析器
SAXParser sax = SAXParserFactory.newInstance().newSAXParser() ;
//获取XML文档的读取器
XMLReader reader = sax.getXMLReader() ;
final List<Book> list = new ArrayList<Book>() ;
//注册内容处理器
reader.setContentHandler(new DefaultHandler(){
Book book = null ;
String curName ; //记录当前标签的名字
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
curName = qName ;
if(qName.equals("书"))
book = new Book() ;
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("书".equals(qName))
list.add(book) ;
curName = null ;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if("书名".equals(curName))
book.setBookName(new String(ch,start,length)) ;
if("作者".equals(curName))
book.setAuthor(new String(ch,start,length)) ;
if("售价".equals(curName))
book.setPrice(Float.parseFloat(new String(ch,start,length))) ;
}
}) ;
//加载文档
reader.parse("src/book.xml") ;
for (Book book : list) {
System.out.println(book);
}
System.out.println(".....");
System.out.println(list);
}
}
a、解析包
* JAXP (sun 公司提供)
* DOM4j (第三方)
b、单元测试
* 搭建环境: 在工程中引入junit包
MyMath.java
public class MyMath {
public int add(int a ,int b){
return a + b ;
}
public int devide(int a ,int b){
return a / b ;
}
}
MyMathTest.java
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class MyMathTest {
/*
* 测试方法的要求:
* 1. 方法必须是公有的
* 2. 返回值必须是void
* 3. 不能有任何形参
* 4. 必须有@Test注解
*
* @Before : 是在每个测试方法执行之前先调用的方法
* @After: 是在每个测试方法执行之后先调用的方法
*
* @BeforeClass: 是在测试方法执行之前先调用的方法(只会调用一次)
* @AfterClass: 是在测试方法执行之前后调用的方法(只会调用一次)
*
* 参数: timeout: 用来定义方法执行的最大时间 (毫秒)
* expected: 指定预期出现的异常元类
* */
static MyMath my ;
// @Before
// public void before(){
// System.out.println("初始化了");
// my = new MyMath() ;
// }
@BeforeClass
public static void before(){
System.out.println("初始化了");
my = new MyMath() ;
}
@Test(timeout=200)
public void testAdd(){
Assert.assertEquals(7, my.add(3, 4) ) ;
}
@Test(expected=ArithmeticException.class)
public void testDevide(){
Assert.assertEquals(2, my.devide(10, 0)) ;
}
// @After
// public void after(){
// System.out.println("结束了");
// }
@AfterClass
public static void after(){
System.out.println("结束了");
}
}
c、测试方法:
1. 测试方法必须是公有的
2. 测试方法必须返回值是void
3. 测试方法必须加@Test
4. 测试方法没有形参
@Test : 代表测试方法
参数timeout: 指定执行方法所需最多时间(毫秒)
expected: 指定方法会出现的异常类型(用元类表示)
@Before : 执行每个测试方法之前都要执行的方法
@After : 执行每个测试方法之后都要执行的方法
@BeforeClass : 执行测试方法之前要执行的方法(静态的,只会执行一次)
@AfterClass : 执行测试方法之后要执行的方法(静态的,只会执行一次)
五、XML练习案例
1、以如下格式的exam.xml文件为例
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<exam>
<student idcard="111" examid="222">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
<student idcard="333" examid="444">
<name>李四</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
2、编程实现如下功能
3、实现学生信息的添加
4、实现学生信息的查询
5、实现学生的删除功能
练习逻辑图:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>
<student examid="222" idcard="111">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
</exam>
Student.java
public class Student {
private String name ;
private String location ;
private int grade ;
private String examid ;
private String idcard ;
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 int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public String getExamid() {
return examid;
}
public void setExamid(String examid) {
this.examid = examid;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
@Override
public String toString() {
return "Student [name=" + name + ", location=" + location + ", grade="
+ grade + ", examid=" + examid + ", idcard=" + idcard + "]";
}
}
JaxpUtils.java
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
//工具类
public class JaxpUtils {
/**
* 获取文档树
* @return
*/
public static Document getDocument(){
//获取DOM解析器
try {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder() ;
Document document = db.parse("src/exam.xml") ;
return document ;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null ;
}
/**
* 将内存中的dom树写入硬盘
* @param document 内存中的dom树
*/
public static void write2xml(Document document){
try {
Transformer tf = TransformerFactory.newInstance().newTransformer() ;
tf.transform(new DOMSource(document), new StreamResult("src/exam.xml")) ;
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
StudentDao.java
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.heima.bean.Student;
import com.heima.utils.JaxpUtils;
public class StudentDao {
/**
* 添加学生
* @param student 要添加的学生
* @return
*/
public boolean addStudent(Student student){
//加载DOM树
Document document = JaxpUtils.getDocument() ;
//创建student节点,依次组合
Element el = document.createElement("student") ;//新建标签
el.setAttribute("examid", student.getExamid()) ;//给标签添加属性
el.setAttribute("idcard", student.getIdcard()) ;//同上
Element nameEl = document.createElement("name") ;
nameEl.setTextContent(student.getName()) ;
Element locationEl = document.createElement("location") ;
locationEl.setTextContent(student.getLocation()) ;
Element gradeEl = document.createElement("grade") ;
gradeEl.setTextContent(student.getGrade() + "") ;
//组合节点
el.appendChild(nameEl) ;
el.appendChild(locationEl) ;
el.appendChild(gradeEl) ;
//将student节点附加到根节点上
document.getDocumentElement().appendChild(el) ;
//写回到硬盘
JaxpUtils.write2xml(document) ;
return true ;
}
/**
* 通过准考证号查询学生
* @param examid 准考证号
* @return
*/
public Student findStudentByExamId(String examid){
//加载DOM树
Document document = JaxpUtils.getDocument() ;
//拿到所有的student节点
NodeList nl = document.getElementsByTagName("student") ;
//循环判断
for (int i = 0; i < nl.getLength(); i++) {
Element n = (Element)nl.item(i) ;
if(n.getAttribute("examid").equals(examid)){
//说明找到了需要的节点
//封装数据
Student s = new Student() ;
s.setExamid(examid) ;
s.setIdcard(n.getAttribute("idcard")) ;
s.setName(n.getElementsByTagName("name").item(0).getTextContent()) ;
s.setLocation(n.getElementsByTagName("location").item(0).getTextContent()) ;
s.setGrade(Integer.parseInt(n.getElementsByTagName("grade").item(0).getTextContent())) ;
return s ;
}
}
return null ;
}
/**
* 通过姓名删除学生
* @param name 学生的姓名
* @return
*/
public boolean deleteStudentByName(String name){
//加载DOM树
Document document = JaxpUtils.getDocument() ;
//拿到所有的name节点
NodeList nl = document.getElementsByTagName("name") ;
//循环判断
for (int i = 0; i < nl.getLength() ; i++) {
Element el = (Element) nl.item(i) ;
if(el.getTextContent().equals(name)){
//找到了需要删除的学生
//爷爷干掉父亲
el.getParentNode().getParentNode().removeChild(el.getParentNode()) ;
//写回到硬盘
JaxpUtils.write2xml(document) ;
return true ;
}
}
return false ;
}
}
StudentView.java
import java.util.Scanner;
import com.heima.bean.Student;
import com.heima.dao.StudentDao;
public class StudentView {
static Scanner scan = new Scanner(System.in) ;
static StudentDao dao = new StudentDao() ;
public static void main(String[] args) {
System.out.println(" 添加学生 (a) 查询学生 (b) 删除学生 (c) ");
System.out.println("请选择操作:");
String op = scan.next() ;
if("a".equalsIgnoreCase(op)){
//添加学生
boolean flag = addStudent() ;
if(flag)
System.out.println("添加成功");
else
System.out.println("添加失败");
}else if("b".equalsIgnoreCase(op)){
//查询学生
Student s = findStudentByExamId() ;
if(s != null)
System.out.println(s);
else
System.out.println("查无此人");
}else if("c".equalsIgnoreCase(op)){
//删除学生
boolean flag = deleteStudentByName() ;
if(flag)
System.out.println("删除成功");
else
System.out.println("删除失败");
}
}
private static boolean deleteStudentByName() {
System.out.println("请输入学生姓名: ");
String name = scan.next() ;
//直接调用dao完成业务逻辑
return dao.deleteStudentByName(name);
}
private static Student findStudentByExamId() {
System.out.println("请输入准考证号:");
String examid = scan.next() ;
//调用dao完成业务逻辑
return dao.findStudentByExamId(examid);
}
private static boolean addStudent() {
System.out.println("请输入姓名:");
String name = scan.next() ;
System.out.println("请输入身份证号:");
String idcard = scan.next() ;
System.out.println("请输入准考证号:");
String examid = scan.next() ;
System.out.println("请输入地址:");
String location = scan.next() ;
System.out.println("请输入分数:");
String grade = scan.next() ;
//封装数据
Student s = new Student() ;
s.setExamid(examid) ;
s.setIdcard(idcard) ;
s.setName(name) ;
s.setLocation(location) ;
s.setGrade(Integer.parseInt(grade));
//做业务逻辑
return dao.addStudent(s) ;
}
}
时间: 2024-10-05 19:30:05