XML加强

jaxp进行sax解析

dom解析:一次性读到内存,占用内存比较大
sax解析:sax的出现就是为了弥补dom解析的缺陷(内存消耗大),sax解析内存消耗小。 读取一部分,解析一部分

sax: Simple Api(for) Xml,来自于开源社区,已经纳入了javase的规范
sax的api在jdk: org.xml.sax.*

sax解析原理: 读到xml文档的某部分内容,就会触发对应的事件处理代码。

package gz.itcast.a_sax;

import javax.xml.parsers.ParserConfigurationException;
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;

//演示sax解析原理

public class Demo1 {

	/**
	 * @param args
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 */
	public static void main(String[] args) throws Exception {
		//1)创建SAXParseFactory对象
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//2)创建SAXParser对象
		SAXParser sp = factory.newSAXParser();
		//3)得到一个xmlreader
		XMLReader reader = sp.getXMLReader();
		//4)xmlreader绑定事件监听器
		reader.setContentHandler(new MyContentHandler());
		//5)开始读取
		reader.parse("src/exam.xml");
	}

}

class MyContentHandler implements ContentHandler{

	@Override
	public void endPrefixMapping(String prefix) throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void ignorableWhitespace(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processingInstruction(String target, String data)
			throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setDocumentLocator(Locator locator) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void skippedEntity(String name) throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void startDocument() throws SAXException {
		System.out.println("读取到了文档开始");
	}
	/**
	 * @param qName: 表示元素名称
	 * @param atts : 属性列表(属性包含在开始元素)
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes atts) throws SAXException {
		System.out.println("读取到了元素开始:"+qName);
	}
	/**
	 * @param ch: 表示到目前为止读到的所有文本内容的数组
	 * @param start: 表示当前读到的文本所处的位置(下标)
	 * @param length: 表示当前读到的文本内容的长度
	 *       xxxxxxxxx张三
	 *               20 22
	 *             ch: 22
	 *            start:20  
	 *            length 2
	 *        读到当前的文本内容    
	 *            new String(ch,start,length) : 张三
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		System.out.println("读取到了文本内容:"+new String(ch,start,length));
	}
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println("读取到了元素结束:"+qName);
	}
	@Override
	public void endDocument() throws SAXException {
		System.out.println("读取到了文档结束");
	}

	@Override
	public void startPrefixMapping(String prefix, String uri)
			throws SAXException {
		
	}
	
}

案例:
1)读取xml指定内容
2)读取xml内容,封装成对象。

sax核心的api:
1)创建SAXParserFactory对象
2)通过SAXParserFactory对象得到SAXParser对象
3)通过SAXParser对象得到XMLReader解析器
4)在XMLReader解析器注册事件监听器(ContentHandlder接口)
5) 使用XMLReader的parse方法进行读取xml文件

ContentHandlder接口常用方法
startDocument(): 文档开始触发
startElement(): 读到元素开始触发
characters(): 读到文本内容触发
endElement(): 读到元素结束触发
endDocument(): 读到文档结束触发

Junit单元测试

开发步骤:
1)建立一个Junit Test Case的类
2)直接在每个方法中写测试逻辑
3)运行测试方法

写Junit的测试方法
1)方法顶部一定要加上@Test注解
2)方法必须是public修饰,不能有返回值,不能有参数,可以抛出异常

查看Junit的测试结果
看junit导航条
绿色: 代表测试通过
红色: 代表测试不通过

运行junit测试方法
1)双击方法,右键“junit test”运行。(运行一个方法)
2) 双击类,右键“junit test”运行。(运行类中多个方法)
3)双击项目,右键“junit test”运行。(运行项目中多个方法)

判断结果
Assert类:
assertEquals()
assertSame()
assertTrue()
assertFalse()

五个常用注解
@Test
@Before
@After
@BeforeClass
@AfterClass

MathUtil

package gz.itcast.b_junit;
//数学工具类
public class MathUtil {

	/**
	 * 加法运算
	 * @param a
	 * @param b
	 * @return
	 */
	public static int add(int a,int b){
		return a+b;
	}
	
	/**
	 *  除法运算
	 * @param a
	 * @param b
	 * @return
	 */
	public static int div(int a,int b){
		return a%b;
	}
	
	
	public static void print(){
		System.out.println("print-=====");
		boolean flag = false;
		if(flag){
			throw new RuntimeException("方法内部的异常");
		}
	}
}

TestMathUtil

package gz.itcast.b_junit;

import junit.framework.Assert;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

// 测试MathUtil

public class TestMathUtil {
	//这个方法需要在每个测试方法之前执行的话,可以加上一个注解@Before
	//@Before
	//如果说要在所有的测试方法之前只执行1次,可以给这个方法加上@BeforeClass(必须是static)
	@BeforeClass
	public static void init(){
		System.out.println("初始化代码");
	}
	
	//这个方法需要在每个测试方法之后执行的话,可以加上@After
	//@After
	//如果说要在所有的测试方法之后只执行1次,可以给这个方法加上@AfterClass(必须是static)
	@AfterClass
	public static void destory(){
		System.out.println("清理代码");
	}

	@Test
	public void testAdd()throws Exception {
		//System.out.println("===");
		int result = MathUtil.add(10, 20);
		/*if(result!=30){
			throw new RuntimeException("结果错误");
		}*/
		
		//使用junit的专业的结果判定的方法
		// Assert工具类: 断言类。用来判定结果
		//Assert.assertEquals(30, result); //相等:测试通过;不相等:测试不通过;
		
		//Assert.assertTrue(true); //true:测试通过;false:测试不通过;
		//Assert.assertFalse(false); //false:测试通过;true:测试不通过;
		
		Cat c1 = new Cat("tom",2);
		Cat c2 = new Cat("tom",2);

		//Assert.assertSame(c1, c2);// 使用==进行比较。
		Assert.assertEquals(c1, c2);//使用equals方法进行比较
	}

	@Test
	public void testDiv() {
		//System.out.println("!!!!!");
		int result = MathUtil.div(20, 10);
		if(result!=2){
			throw new RuntimeException("结果错误");
		}
	}
	

	@Test
	public void testPrint() {
		MathUtil.print();
	}

}


class Cat{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Cat(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Cat other = (Cat) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
}

DOM4J基本使用

dom4j:用过jaxp,使用dom4j可以更加简单地操作xml(也是基于dom解析原理的工具)

1)读取xml文件:
//1)创建SAXReader对象
SAXReader reader = new SAXReader();
//2)读取xml文件
Document doc = reader.read(“src/exam.xml”);

查询:
元素相关的:
element(“name”)
elements(“name”);

属性相关的:
attribute(“name”)
attributeValue(“name”)

文本相关的:
getText()

2)写出xml文件
//1)创建一个XMLWriter对象
XMLWriter writer = new XMLWriter(
new FileOutputStream(“src/exam.xml”));
//2)写出xml文件
writer.write(doc);
//3)关闭流
writer.close();

创建或修改:
addElement(“name”) 添加元素
addAttribute(“name”,“value”);// 添加属性
setText(“value”) 添加文本

删除:
detach()
getParent().remove(elem);
XML文件

<?xml version="1.0" encoding="UTF-8"?>
<exam>
	<student examid="222" idcard="111">
		<name>张三</name>
		<location>沈阳</location>
		<grade>89</grade>
	</student>
	
	<student idcard="333">
		<name>李四</name>
		<location>大连</location>
		<grade>97</grade>
	</student>
	<location>小连</location>
</exam>

学习dom4j的基本使用

package gz.itcast.c_dom4j;

import java.io.FileOutputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

// 目标: 学习dom4j的基本使用
public class Demo1 {
	Document doc = null;
	
	@Before
	public void init() throws Exception{
		//1)创建SAXReader对象
		SAXReader reader = new SAXReader();
		//2)读取xml文件
		doc = reader.read("src/exam.xml");
	}
	@After
	public void write2xml() throws Exception{
		//写出到xml文件中
		//1)创建一个XMLWriter对象
		XMLWriter writer = new XMLWriter(
				new FileOutputStream("src/exam.xml"));
		//2)写出xml文件
		writer.write(doc);
		//3)关闭流
		writer.close();
	}

	//读取xml文件
	@Test
	public void test1() throws Exception{
		//1)创建SAXReader对象
		SAXReader reader = new SAXReader();
		//2)读取xml文件
		Document doc = reader.read("src/exam.xml");
		System.out.println(doc);
	}
	
	//查找节点:
	// 元素  /  属性   / 文本
	// 元素:第二个 <location>
	@Test
	public void test2(){
		//1)根元素
		Element root = doc.getRootElement();
		System.out.println(root.getName());
		//注意:dom4j的优势在于操作的api都是符合常用的标准(例如集合.java.uitl.*)
		List list = root.elements("student");//exam下的所有student元素
		//方式一:
		/*for(int i=0;i<list.size();i++){
			list.get(i);
		}*/
		//方式二:
		/*for(Object obj:list){
			
		}*/
		//方式三: 迭代器   hasNext() 判断是否有下一个元素  next(): 取出下一个元素
		/*Iterator it = list.iterator();
		while(it.hasNext()){
			it.next();
		}*/
		
		Element stuElem = (Element)list.get(1);
		Element locElem = stuElem.element("location");// 在student元素下查询一个指定名称的元素
		System.out.println(locElem);
		
		System.out.println(stuElem.attribute("examid").getValue());//查询属性值
		System.out.println(stuElem.attributeValue("examid"));//查询属性值
		
		System.out.println(locElem.getText());//文本内容
		
	}
	
	//创建或修改:
	// 元素 、  属性  、 文本
	@Test
	public void test3() throws Exception{
			//1)创建<student>
			Element root = doc.getRootElement();
			Element stuElem = root.addElement("student");
			//2)在新的<student>再新建一个examid和idcard属性
			stuElem.addAttribute("examid", "555");
			stuElem.addAttribute("idcard", "666");
			//3)在<student>下新建立一个<name>
			Element nameElem = stuElem.addElement("name");
			//4)设置<name>的文本内容为“王五”
			nameElem.setText("王五");
	}
	
	//删除节点:
	// 元素  、 属性
	@Test
	public void test4(){
		//Element stuElem = (Element)doc.getRootElement().elements("student").get(2);
		//stuElem.detach();//自杀
		//stuElem.getParent().remove(stuElem);//它杀
		
		Element stuElem = (Element)doc.getRootElement().elements("student").get(1);
		stuElem.attribute("examid").detach();
	}
	
	//学习xpath的基本使用(回去查询xpath文档学习)
	@Test
	public void test5(){
		//需求: 删除第二个<grade>
		// 1)快速找到<grade>
		Element gElem = (Element)doc.selectSingleNode("//student[2]");
		//gElem.detach();
		
		//2) 找第二个<location>
		//List nodes = doc.selectNodes("//location[1]");
		// 找examid属性值为222的student
		List nodes = doc.selectNodes("//student[@examid='222']");
		for (Object object : nodes) {
			System.out.println(object);
		}
	}
	
}

xpath基本使用
xpath一句话概括: 非常方便的读取xml节点。

遇到了xml的层次结构非常深的时候,使用dom4j获取时很麻烦的!!这时就可以使用xpath。

核心的方法:
List list = document.selectNodes( “//foo/bar” ); 查询多个节点
Node node = document.selectSingleNode( “//foo/bar/author” ); 查询一个节点

xpath的常用语法:
/ 代表根(从根开始找)
// 所有子节点(不分层次)

schema约束

链接:https://www.w3school.com.cn/schema/schema_simple.asp
目标: 能够看着scheme约束来学有效的xml文件
重点:使用名称空间导入schema文件
第一步:找到schema的名称空间,在xml文件中定义这个名称空间,给该名称给短名称
第二步:在xml文件中定义名称空间对应的schema文件地址
第三步:定义一个xsi的名称空间,w3c组织的标准名称空间
<itcast:书架 xmlns:itcast=“http://www.itcast.cn”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://www.itcast.cn book.xsd”>
总结需要掌握的内容:
会写一个XML,会读取XML,语法:元素定义、属性定义、文档声明; 约束:DTD约束/Schema约束
公用组件:
struts, DTD约束
hibernate, DTD约束
Spring, Schema约束
DOM解析
sun公司定义的统一技术规范
DOM4J 解析技术
SAX解析
sun公司定义的技术

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值