1、sax的使用
sax不能做增删改,只能做查。
sax解析
在使用DOM解析XML文档时,需要读取整个XML文档,在内存中构架代表整个DOM树的Document对象,从而再对XML文档进行操作。在这种情况下,如果XML文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
sax解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会对文档进行操作。
sax采用事件处理的方式解析XML文件,利用sax解析XML文档,涉及两个部分:解析器和事件处理器。
解析器可以使用JAXP的API创建,创建出sax解析器后,就可以指定解析器去解析某个XML文档。
解析器采用sax方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的XML文件内容作为方法的参数,传递给事件处理器。
事件处理器有程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松的得到sax解析器解析到的数据。从而可以决定如何对数据进行处理。
阅读ContentHandler API文档,常用方法:startElement,endElement,characters
这个是XML文件。
<?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>
<student examid="1111" idcard="5555">
<name>张三</name>
<location>大连</location>
<grade>97</grade>
</student>
<student>
<name>李四</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
这个是Java代码。
package cn.itcast.sax;
import java.io.IOException;
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;
import org.xml.sax.helpers.DefaultHandler;
public class Demo1 {
/**
* sax方式解析book.xml文件
* @param args
* @throws SAXException
* @throws ParserConfigurationException
* @throws IOException
*/
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
// TODO Auto-generated method stub
//1.创建工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.用工厂创建解析器
SAXParser sp = factory.newSAXParser();
//3.利用解析器得到reader
XMLReader reader = sp.getXMLReader();
//4.在解析xml文档之前,设置好事件处理器
//这里使用new MyContentHandler2() 或者new MyContentHandler()
reader.setContentHandler(new MyContentHandler2());
//5.利用reader读取xml文档
reader.parse("src/student.xml");
}
}
//用于获取指定内容
class MyContentHandler2 extends DefaultHandler{
private boolean isOK = false;
private int index = 1;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if(qName.equals("name")){
isOK = true;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
if(qName.equals("name")){
isOK = false;
index++;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
if(isOK==true && index==1){
System.out.println(new String(ch,start,length));
}
}
}
//得到xml文档内容的事件处理器
class MyContentHandler implements ContentHandler{
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
// TODO Auto-generated method stub
System.out.println("当前解析到了:"+qName+",这个标签是开始标签");
for(int i=0;i<atts.getLength();i++){
String attname = atts.getQName(i);
String attvalue = atts.getValue(i);
System.out.println(attname + "=" +attvalue);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
System.out.println("当前解析到了:"+qName+",这个标签是结束标签");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
System.out.println("当前解析到了内容:"+new String(ch,start,length));
}
@Override
public void setDocumentLocator(Locator locator) {
// TODO Auto-generated method stub
}
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
// TODO Auto-generated method stub
}
@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 skippedEntity(String name) throws SAXException {
// TODO Auto-generated method stub
}
}
2、DOM4J解析XML文档
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,单它提供了比JDOM更好的灵活性。
Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
使用Dom4j开发需要下载dom4j相应的jar文件。
下面看使用DOM4J对XML文档进行操作。
这个是student.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<exam>
<student examid="1111" idcard="5555">
<name>张五</name>
<班级>三班</班级>
<location>大连</location>
<grade>97</grade>
</student>
<student>
<name>李四</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
这个是Java源代码
package cn.itcast.dom4j;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
public class Demo1 {
//读取xml文档数据
@Test
public void read() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element root = document.getRootElement();
Element studentname = root.element("student").element("name");
System.out.println(studentname.getText());
}
//获取属性
@Test
public void readAttr() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element root = document.getRootElement();
String value = root.element("student").attributeValue("examid");
System.out.println(value);
}
//向xml文档中添加<班级>三班</班级>
@Test
public void add() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element class_1 = DocumentHelper.createElement("班级");
class_1.setText("三班");
document.getRootElement().element("student").add(class_1);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/student.xml"));
writer.write(document);
writer.close();
}
//更新
@Test
public void update() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element name = (Element) document.getRootElement().element("student").elements("name").get(0);
name.setText("张五");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/student.xml"));
writer.write(document);
writer.close();
}
//删除
@Test
public void delete() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element class_1 = (Element) document.getRootElement().element("student").elements("班级").get(0);
class_1.getParent().remove(class_1);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/student.xml"));
writer.write(document);
writer.close();
}
//往指定位置增加节点
@Test
public void add2() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element class_1 = DocumentHelper.createElement("班级");
class_1.setText("三班");
List list = document.getRootElement().element("student").elements();
list.add(1, class_1);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/student.xml"));
writer.write(document);
writer.close();
}
}
3、XPath
package cn.itcast.dom4j;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
public class Demo1 {
//使用XPath
@Test
public void findWithXpath() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/student.xml"));
Element e = (Element) document.selectNodes("//student").get(1);
System.out.println(e.element("name").getText());
}
@Test
public void findUser() throws Exception{
String username = "aab";
String password = "123";
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/users.xml"));
Element e = (Element) document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");
if(e!=null){
System.out.println("用户登录成功!!");
}else{
System.out.println("用户名和密码不正确!!");
}
}
}
4、XML Schema
XML Schema也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的局限性。
XML Schema符合XML语法结构。
DOM,SAX等XML API很容易解析出XML Schema文旦中的内容。
XML Schema对名称空间支持非常好。
XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。
XML Schema定义约束的能力非常大,可以对XML实例文档做出细致的语义限制。
XML Schema不能像DTD一样定义实体,比DTD更复杂,单XML Schema现在已经是w3c组织的标准,正在逐步取代DTD。
Schema约束快速入门
XML Schema 文件自身就是一个XML文件,但是它的扩展名通常为.xsd
一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。
和XML文件一样,一个XML Schema文档也必须有一个根节点,但是这个根节点的名称为Schema。
编写一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URL地址上,在XML Schema技术中有一个专业术语描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URL(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。
下面是book.xsd的代码
<?xml version="1.0" encoding="UTF-8" ?>
<xs: schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.cn" elementFormDefault="qualified">
<xs:element name='书架' >
<xs:complexType>
<xs:sequence maxOccurs="unbounded" >
<xs:element name='书' >
<xs:complexType>
<xs:sequence>
<xs:element name='书名' type='xs:string' />
<xs:element name='作者' type='xs:string' />
<xs:element name='售价' type='xs:string' />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
下面是book.xml的代码
<?xml version="1.0" encoding="UTF-8" ?>
<itcast:书架 xmlns:itcast="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn book.xsd">
<itcast:书>
<itcast:书名>JavaScript网页开发</itcast:书名>
<itcast:作者>张孝祥</itcast:作者>
<itcast:售价>28.00元</itcast:售价>
</itcast:书>
</itcast:书架>
名称空间的概念
在XML Schema中,每个约束模式文档都可以被赋予一个唯一的名称空间,名称空间用一个唯一的URI(Uniform Resource Identifier,统一资源标识符)表示。在XML文件中书写标签时,可以通过名称空间声明(xmlns),来声明当前编写的标签来自哪个Schema约束文档。如:
<itcast:书架 xmlns:itcast="http://www.itcast.cn" >
<itcast:书>...</itcast:书>
</itcast:书架>
此处使用itcast来指向声明的名称,以便于后面对名称空间的引用。
注意:名称空间的名字语法容易让人混淆,尽管以http://开始,那个URI并不指向一个包含模式定义的文件。事实上,这个URI:http://www.itcast.cn根本没有指向任何文件,只是一个分配的名字。
使用名称空间引用Schema
为了在一个XML文档中声明它所遵循的Schema文件的具体位置,通常需要在XML文档中的根节点中使用schemaLocation属性来指定,例如:
<itcast:书架 xmlns:itcast="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn book.xsd">
schemaLocation此属性有两个值,第一个值是需要使用的命名空间。第二个值是供命名空间使用的XML schema的位置,两者之间用空格分开。
注意,在使用schemaLocation属性时,也需要指定该属性来自哪里。
使用默认名称空间
基本格式:xmlns=”URI”
举例:
<书架 xmlns="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.cn book.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
使用名称空间引入多个XML Schema文档
文件清单:xmlbook.xml
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns="http://www.it315.org/xmlbook/schema" xmlns:demo="http://www.it315.org/demo/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.it315.org/xmlbook/schema http://www.it315.org/xmlbook.xsd http://www.it315.org/demo/schema http://www.it315.org/demo.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价 demo:币种="人民币">28.00元</售价>
</书>
</书架>
不使用名称空间引入XML Schema文档
文件清单
<?xml version="1.0" encoding="utf-8" ?>
<书架 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xmlbook.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
Schema语法
查看xsd.chm文档。