posts - 37, comments - 8, trackbacks - 0, articles - 0

jsp程序设计:DOM+SAX操作xml

Posted on 2008-10-24 07:02 梦与桥 阅读(718) 评论(0)  编辑  收藏 所属分类: jsp程序设计
1、操作XML文件的开源软件包括DOM、SAX、JDOM等,程序员需要熟悉并掌握这些常用的接口的使用,能够通过这些接口编写java语句来实现对XML文件的处理。
2、DTD主要有下列几方面的作用:
1)可以验证XML文件数据的有效性。
2)可以为某类XML文件提供统一的格式和相同的结构。
3)可以保证在一定的范围内,XML文件数据的交流和共享。
4)应用程序设计人员根据DTD就能够知道对应XML文件的逻辑结构,从而编写出相应的处理应用程序。
3、在DTD中引进Namespaces这个概念是为了解决命名冲突问题,设置url并不是说真的要到那个网址去读取,仅仅作为一种区别的标志而已。
4、DOM
1)DOM的类
目前主流的解析器有:JAXP(Java Api for XML Processing)、Xerces(Apache)、XML4J(IBM)和xalan等,主流的解析器都支持SAX和DOM,支持JDOM的解析器目前只有SUN公司发布的jdom包。DOM即文件对象模型。在应用程序中,基于DOM的XML分析器将一个XML文件转换成了一个对象模型的集合(通常被称为DOM树),应用程序可以通过对该对象模型的操作,实现对XML文件中数据的操作。
    §Document类,描述了整个XML的文件语法结构,它包含了一系列Node类形成的树形结构。程序员可以先扫描XML源文件,得到相应的Document对象,遍历这颗树来得到XML文件的所有内容,这是对XML文件操作的起点。
    §Node对象,Node类是DOM结构中最为基本的类,经描述了文件树中的一个抽象的节点。它包含类型为Element、Attr、Text和其他类的特征。Node对象引用其成员的变量来操作XML文件。
    §NodeList对象,代表了一个包含了一个或者多个Node的列表。
    §Element对象,Element类描述XML文件中的标志元素,继承于Node,也是Node的最主要的子对象。标志中要以包含属性,因而Element对象中有存取其属性的方法,而任何Node中定义的方法,Element都继承下来。
    §Attribute对象,它代表了某个标志的属性。继承Node,但因为Attr实际上包含在Element中,不能被看作Element的子对。在DOM中Attributer并不是DOM树的一个节点,所以Node中的getparentNode()、getpreviousSibling()和getnextSibling()返回的都将是null。即,Attribute是Element类的一部分,并不作为DOM树中单独的一个节点出现。
DOM类在DOM中都是用接口语言IDL定义的,因而,DOM可以映射到任何面向对象的语言,只要它实现了DOM所定义的接口就可以了。许多公司和厂家都提供了符合DOM规范的DOM接口和程序包。以微软的DOM接口为例:
2)DOM读取XML文件,通常用到以下5个基本步骤:
    建立一个解析器工厂。
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstace();
    利用工厂获得一个具体的解析器对象。
DocumentBuilder builder=factory.newDocumentBuilder();
    ƒ利用DocumentBuilder的parse()方法接受一个XML文件名作为输入参数,返回一个Document对象。Document对象代表了一个XML文件的树模型。
Document doc=builder.parse("file.xml");
    使用Document对象的getElementsByTagName()方法,我们可以得到一个NodeList对象,它是XML文件中的标签元素列表,可以使用NodeList对象的item()方法来得到列表中的每一个Node对象。
NodeList nl=doc.getElementsByTagName("person");
Element node
=(Element)nl.item(i);
    通过Node对象的getNodeValue()方法提取某个标签内的内容。
node.getElementsByTagName("NAME").item(0).getFirstChild().getNodeValue();
3)DOM读取XML文件实例:本实例有两个文件(book.xml与bookDisplay.jsp)
book.xml的代码如下:
<?xml version="1.0" encoding="gb2312"?>
<books>
<book>
<name>J2EE编程技术</name>
<author>郝玉龙等</author>
<price cointype="¥">27.00元</price>
<publish>清华大学出版社</publish>
<date>
<day>15</day>
<month>3</month>
<year>2005</year>
</date>
</book>
<book>
<name>JSP大学实用教程</name>
<author>耿祥义等</author>
<price cointype="¥">24.00元</price>
<publish>电子工业出版社</publish>
<date>
<day>21</day>
<month>9</month>
<year>2007</year>
</date>
</book>
<book>
<name>JAVA2游戏编程</name>
<author>Thomas Petchel</author>
<price cointype="$">10.00元</price>
<publish>清华大学出版社</publish>
<date>
<day>1</day>
<month>8</month>
<year>2005</year>
</date>
</book>
<book>
<name>JSP应用开发</name>
<author>邓子云等</author>
<price cointype="¥">49.00元</price>
<publish>机械工业出版社</publish>
<date>
<day>11</day>
<month>12</month>
<year>2007年</year>
</date>
</book>
</books>
bookDisplay.jsp的代码如下:
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.xml.parsers.*,org.w3c.dom.*"%>
<html>
<head>
<title> DOM读取book.xml</title>
</head>
<body>
<table border=1 align="center">
    
<!--输出表头-->
    
<tr bgcolor="yellow">
        
<td>书名</td>
        
<td>作者</td>
        
<td>定价</td>
        
<td>出版社</td>
        
<td>出版日期</td>        
    
</tr>
<%
    DocumentBuilderFactory factory
=DocumentBuilderFactory.newInstance();
    DocumentBuilder builder
=factory.newDocumentBuilder();
        //此处用的是绝对路径,相对路径不太好使。
    Document doc
=builder.parse("C:/Program Files/Apache Software Foundation/Tomcat 6.0/webapps/readXml/book.xml");
    doc.normalize();
    NodeList books
=doc.getElementsByTagName("book");
    
for(int i=0;i<books.getLength();i++){
        Element book
=(Element)books.item(i);
        out.print(
"<tr>");
        out.print(
"<td>"+book.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("author").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("price").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("publish").item(0).getFirstChild().getNodeValue()+"</td>");
        Element bookdate
=(Element)book.getElementsByTagName("date").item(0);
        
String day=bookdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();
        
String month=bookdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();
        
String year=bookdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();
        out.print(
"<td>"+year+""+month+""+day+""+"</td>");
        out.println();
    }
  
%>
</table>
</body>
</html>

4)DOM修改XML文件
修改XML文件就是在修改了DOM树后重新写入到XML文件中去,通常会遇到两个方面的问题:
    Œ在XML文件中增加记录:首先要在DOM树中增加一个节点元素,然后在这个节点元素上增加子节点元素,并给相应的叶节点赋值,最后把DOM树保存到XML文件中。
    在XML文件中修改节点的值,要修改XML文件中节点的值,需要先将XML文件读入到DOM树中,再遍历DOM树,并在遍历的过程中找到相应的节点并修改其值,并把修改的DOM保存到XML文件中。
5)DOM修改XML文件实例,所操作的XML文件依然是book.xml,用以创修改book.xml文件的文件是bookChange.jsp,代码如下:

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.xml.parsers.*, javax.xml.transform.*,javax.xml.transform.dom.*"%>
<%@ page import="javax.xml.transform.stream.*,java.io.*, org.w3c.dom.*"%>
<html>
<head>
<title>DOM修改XML文件实例</title>
</head>
<body>
<%
DocumentBuilderFactory factory
=DocumentBuilderFactory.newInstance();
DocumentBuilder builder
=factory.newDocumentBuilder();
Document doc
=builder.parse("C:/Program Files/Apache Software Foundation/Tomcat 6.0/webapps/readXml/book.xml");
doc.normalize();
//---取得变量---
String name="精通Java EE项目案例";
String author="刘乃丽";
String price="85.00元";
String publish="人民邮电出版社";  
//---创建一个book对象---
Text textseg;
Element book
=doc.createElement("book");
//XML文件中添加一个book项目的具体元素
Element bookname
=doc.createElement("name");
textseg
=doc.createTextNode(name);
bookname.appendChild(textseg);
book.appendChild(bookname);
Element bookauthor
=doc.createElement("author");
textseg
=doc.createTextNode(author);
bookauthor.appendChild(textseg);
book.appendChild(bookauthor);
Element bookprice
=doc.createElement("price");
textseg
=doc.createTextNode(price);
bookprice.appendChild(textseg);
book.appendChild(bookprice);
Element bookpublish
=doc.createElement("publish");
textseg
=doc.createTextNode(publish);
bookpublish.appendChild(textseg);
book.appendChild(bookpublish);
String day="01";
String month="01";
String year="2008";
Element bookdate
=doc.createElement("date");
Element bookdateday
=doc.createElement("day");
textseg
=doc.createTextNode(day);
bookdateday.appendChild(textseg);
Element bookdatemonth
=doc.createElement("month");
textseg
=doc.createTextNode(month);
bookdatemonth.appendChild(textseg);
Element bookdateyear
=doc.createElement("year");
textseg
=doc.createTextNode(year);
bookdateyear.appendChild(textseg);
bookdate.appendChild(bookdateday);
bookdate.appendChild(bookdatemonth);
bookdate.appendChild(bookdateyear);
book.appendChild(bookdate);
//创建好的节点添加到DOM树中
doc.getDocumentElement().appendChild(book);
//用xslt把DOM树输出
TransformerFactory tFactory
=TransformerFactory.newInstance();
Transformer transformer
=tFactory.newTransformer();
DOMSource source
=new DOMSource(doc);
StreamResult result
=new StreamResult(new File("C:/Program Files/Apache Software Foundation/Tomcat 6.0/webapps/readXml/book.xml"));
transformer.transform(source,result);
%>
<table border=1 align="center">
    
<!--输出表头-->
    
<tr bgcolor="yellow">
        
<td>书名</td>
        
<td>作者</td>
        
<td>定价</td>
        
<td>出版社</td>
        
<td>出版日期</td>        
    
</tr>
<% 
    
//修改后读取数据
    NodeList books
=doc.getElementsByTagName("book");
    
for(int i=0;i<books.getLength();i++){
        book
=(Element)books.item(i);
        out.print(
"<tr>");
        out.print(
"<td>"+book.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("author").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("price").item(0).getFirstChild().getNodeValue()+"</td>");
        out.print(
"<td>"+book.getElementsByTagName("publish").item(0).getFirstChild().getNodeValue()+"</td>");
        bookdate
=(Element)book.getElementsByTagName("date").item(0);
        
day=bookdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();
        
month=bookdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();
        
year=bookdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();
        out.print(
"<td>"+year+""+month+""+day+""+"</td>");
        out.println();
    }
%>    
</table>
</body>
</html>
5、SAX
1). SAX ( Simple Application interface for XML ), 是一组程序设计接口,采用 observer 模式,将XML文件视为一个文字流的数据,在读取XML 元素时触发一系列的事件

2). 使用DOM 时是将xml 文件解析为一个树状结构,并对树中的节点进行操作
使用SAX 加载XML文件时,他的操作像打开一个“顺序的文件字符流”,在读到XML元素的开始标记,结尾标记和内容标记时将产生一系列的事件
如一个简单的XML文件:<hello><message>hello XML!</message></hello>
会相应的触发:startDocument, startElement, characters, endElement, endDocument, 只需编写这些事件处理程序就可以解析XML文件了

3). SAX 可以高效的使用内存,因为SAX 只是顺序的读取XML 文件的内容,并不会将XML 文件完全加载,这样就比DOM 的处理效率高
但SAX 只能读取XML 文件的内容,而不能更改XML 的内容,也不能随机访问XML 元素

4). 在SAX 中有4个处理器是要实现的:ContentHandler,DTDHandler,EntityResolver,ErrorHandler,以处理不同的事件,这是比较麻烦的,
幸好SAX 定义了一个 DefaultHandler 类把这几个实现了,我们只需在 DefaultHandler中定义事件处理方法,然后注册到XMLReader,而SAXParser封装了XMLReader的实现类,
SAXParser又是由SAXParserFactory提供的,所以我们实际用到的类只有:SAXParserFactory,SAXParser,DefaultHandler

5). SAX 的解析步骤:
(1)写一个类继承 DefaultHandler, 实现自己的事件处理方法
(2)在主程序中建立 SAXParserFactory
(3)可以设置这个factory 的参数
(4)从这个factory 得到SAXParser
(5)解析XML文件
6)SAX解析XML实例,被解析的文件依然是book.xml,用以解析的文件是bookSaxDisplay.jsp,其代码如下:
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="javax.xml.parsers.*,
                org.xml.sax.*,
                org.xml.sax.helpers.
*,
                org.xml.sax.helpers.DefaultHandler,
                java.io.
*"
%>

<html>
  
<head><title>用SAX解析并遍历user.xml</title></head>
  
<body>
<%!
static class SAXParseUser extends DefaultHandler{
    StringBuffer tempString
=new StringBuffer();
    
//文档解析开始
    
public void startDocument() throws SAXException {
        tempString.append(
"开始解析xml文件<br>");
    }
    
//标签解析开始
    
public void startElement(String namespaceURI, String localName,String qName, Attributes atts) throws SAXException{
        tempString.append(
"开始解析结点,结点名称:"+qName+"<br>");
        
//解析得到标签所有的属性
        
for(int i=0;i<atts.getLength();i++){
            tempString.append(
"&nbsp;&nbsp;属性"+atts.getQName(i)+",值为:"+atts.getValue(i)+"<br>");        
        }
    }
    
//标签解析结束
    
public void endElement(String namespaceURI,String localName,String qName) throws SAXException{
        tempString.append(
"解析结点结束,结点名称:"+qName+"<br>");
    }
    
//字符串解析
    
public void characters(char[] ch,int start,int length){
        tempString.append(
"&nbsp;&nbsp;解析出字符串,值为:'"+(new String(ch,start,length))+"'<br>");    
    }
    
//文档解析结束
    
public void endDocument() throws SAXException {
        tempString.append(
"解析xml文件结束!<br>");
    }
    
//得到解析结果
    
public StringBuffer getPrintXML(){
        return tempString;
    }
}
%>
<%    //生成SAX解析器工厂长
    SAXParserFactory spf 
= SAXParserFactory.newInstance();
    XMLReader xmlReader 
= null;
    SAXParser saxParser
=null;
    SAXParseUser saxParseUser
=new SAXParseUser();
    
String filename=pageContext.getServletContext().getRealPath("/book.xml");
    try {
        
// 创建一个解析器SAXParser对象
        saxParser 
= spf.newSAXParser();
        
// 得到SAXParser中封装的SAX XMLReader
        xmlReader 
= saxParser.getXMLReader();
        
//设置解析时处理事件的对象
        xmlReader.setContentHandler(saxParseUser);
        
//开始解析XML文件
        xmlReader.parse(filename);
    }catch (Exception ex) {
        System.out.println(ex);
    }
%>      
       
<!--输出解析结果-->
    
<table border=1>
    
<!--输出表头-->
    
<tr >
        
<td align="center">内容</td>
            
    
</tr>
<%
        out.println(
"<td>"+saxParseUser.getPrintXML()+"</td>");    
%>  
 
</table>
 
</body>
</html>

只有注册用户登录后才能发表评论。


网站导航: