8在JSP中使用XML

XML是万维联盟定义的一种语言,是表示结构化数据的行业标准。XML不仅提供了直接在数据上工作的通用方法,而且XML的威力在于将用户界面和结构化数据相分离。XML文件就是按照XML语言编写的文本文件。


XML解析器是XML和应用程序之间的一个软件组织,其目的是为应用程序从XML文件中解析出所需要的数据。现在普遍使用的XML解析器都是Java语言编写的。


1XML文件的基本结构
XML是extensible Markup Lanuage缩写,称之为可扩展标识语言。所谓可扩展性是指XML允许用户按照XML的规则自定义标记。XML文件是由标记构成的文本文件,与HTML文件不同的是,这些标记可以自由定义,其目的是使得XML文件能够很好的体现数据的结构和含义。


例:

<列车时刻表>

<开车时间>20点58分
<终到时间>08点18分


<开车时间>23点12分
<终到时间>07点25分




XML声明
XML声明必须是XML文件的首行。一个规范的XML文件应当以XML声明作为文件的第一行,在其前面不能有空白、其他的处理指令或注释。



XML声明的版本属性
一个简单的XML声明中可以只包含属性version,目前该属性的值只可以取1.0,指出该XML文件中使用的XML版本。


XML声明中的编码属性
XML声明中也可以指定encoding属性的值,该属性规定XML文件采用哪种字符集进行编码。该属性的默认值为UTF-8。
如:


声明指定encoding属性的值是UTF-8编码。如果XML使用UTF-8编码,那么标记以及标记的内容就可以使用汉字、日文、英文等。如果encoding属性的值为UTF-8,XML文件必须选择UTF-8编码来保存。如果在编写XML文件时只准备使用ASCII字符和汉字,也可以将encoding属性的值设置为gb2312。这时XML文件必须使用ANSI编码保存。如果只准备使用ASCII字符,也可以将encoding属性的值设置为ISO-8859-1。


根标记
XML文件有且仅有一个根标记,其他标记都必须封装在根标记中。上例中<列车时刻表>...就是根标记。


树型结构
一个标记的内容可以包含文本或其他的标记,其中被包含的标记称为该标记的子标记。如果一个标记仅仅包含文本,这样的标记称作叶标记。XML文件的标记必须形成树型结构,即一个标记的子标记必须包含于该标记的开始标记和结束标记之间。


2标记
XML文件是由标记构成的文本文件。标记的名称可以由字母、数字、下划线、点或连字符组成。但必须以字母或下划线开头且中间不能有空格。标记名称不区分大小写。


空标记
所谓空标记是不含有任何内容的标记,即不含有子标记或文本内容。由于空标记不含有任何内容,所以空标记不需要开始标记和结束标记,空标记以<标识开始,用/>标识结束。空标记的语法格式分别为:
<空标记的名称 属性列表/>或<空标记的名称/>


注意在<和标记名称之间不要含有空格。


非空标记
非空标记必须由开始标记与结束标记组成,开始标记与结束标记之间是该标记所含有的内容。


开始标记是以<标识开始,用>标识结束。<标识与>标识之间是标记的名称和属性列表。非空标记的语法格式:
<标记的名称 属性列表>或<标记名称>


结束标记以标识结束。标识之间是标记的名称。


3CDATA段
XML有5种字符属于特殊字符,它们是<、>、&、'、"。这些特殊的字符,XML有特殊的用途,标记内容中的文本数据中不可以有这些特殊字符。如果标记的内容想使用这些特殊字符,需通过使用CDATA段。


CDATA段用作为段的结束,段的开始和段结束之间称为CDATA段的内容。W3C规定,CDATA段中不可以嵌套另一个CDATA段。


属性
属性是指标记的属性,可以为标记添加附加信息。属性是一个名值对,即属性必须由名字和值组成。用=为属性指定一个值。语法如下:
<标记名称 属性列表>...


<标记名称 属性列表/>


处理指示
处理指示是用来给处理XML文件的应用程序提供信息的,所有的处理指示应该遵循下面的格式:

就是说,XML分析器可能对它不干兴趣,而把这些信息原封不懂地传给XML应用程序,然后,这个应用程序来解释这个指示,遵照它所提供的信息进行处理。例:



样式表声明
从本质上讲,样式声明和XML声明一样,这两者都是处理指示的一种,但只有需要对XML文档进行解析的时候,才需要给出这两个处理指示。


文档类型声明
为了对XML进行文档类型的定义,在XML文档中必须进行文档类型的说明,一般在XML、样式表声明之后。如:





什么是DTD
XML的精髓就是基于信息描述的,能够体现数据信息之间逻辑关系的,可以确保文件易读性和易搜索性的自定义标记。为了支持词汇表,XML提供一种定义文档结构与元素的机制,这就是文档类型定义。DTD正是把元素、元素属性、实体等包容进来,给整个文档提供声明保证文档的有效性。DTD是Document Type Definition的简写,意思是文档类型定义。简而言之,DTD规定一个语法分析器为了解释一个有效的XML文件所需要知道的所有规则的细节。


DTD可以是一个完全独立的文件,也可以在XML文件中直接设定。所有DTD分为外部DTD(在XMl文件中条用另外已经编辑好的DTD)和内部DTD(在XML文件中直接设定DTD)两种。


在XML所描述的指示语言中,DTD便提供了语法规定,以便各个语言要素赋予一定的顺序,为了说明特定的语法语法规则,DTD采用一系列正则式,语法分析器将这些正则式与XML文件内部的数据模式相匹配,从而判别一文件是否有效的。匹配被严格执行,因此,如果XML文件中有任何信息不符合DTD规定,都不会通过。DTD的基本格式是:

其中!DOCTYPE是关键字表示文档类型定义开始,而[]中则包括了文档类型定义的实际内容。
!ELEMENT、!ALLIST这两个关键字,它们分别承担了元素组成、类型的定义和元素属性、类型的定义。


DTD语法:
DTD有4中类型的声明,即元素类型声明、属性列表声明、实体声明、符号声明。
元素类型声明(ETD)


上面是两个典型元素的声明。第一个元素类型声明定义了一个元素,并规定该元素必须有NAME和ADDRESS两个子元素,而且NAME的位置必须在ADDRESS的前面。第二个元素类型声明也定义了一个,并规定该元素由纯文本的一般字符组成。元素类型声明不但说明了每个文件中可能存在的元素,给出元素的名字,而且给出元素的具体类型。元素类型声明应该采用如下结构:



事实上根据XML的标准可以将元素内容划分为4类:空元素类型、ANY元素类型、父元素类型、混合元素类型。
空元素类型
空元素类型定义方式为:

这类元素在XML文档中使用空元素标记,元素中没有内容。例:


]>
<学生>


ANY元素类型
ANY元素类型定义方式为:

XML文档里该元素中可以包含任何内容,建议一般只把文档的根元素规定为ANY类型。


]>
<学生>

"有效的"XML文件规定文件中所使用的任何元素都必须在DTD中给出定义,不过并不是所有这种根元素的组成部分都需要另加说明,纯文本字符就是一个例外,ANY定义下的根元素使用纯文本是不需要说明的。


父元素类型
这类元素中可以包含子元素,在DTD中通过正则表达式规定子元素表现的顺序和次数。父元素类型的声明就可以有各种灵活而多样的形式,各种形式之间主要是在子元素出现的顺序、出现的次数以及各个子元素之间的符合关系这几方面存在这差异。要搞清楚它们的区别,熟悉正则表达式中元字符的含义:
空格:不要求严格遵从顺序要求。
,:AND,要求严格遵从顺序要求。
+:出现一次或多次。
*:出现零次或多次。
?:可选,不出现或出现一次。
():一组要共同匹配的表达式。
|:OR,或。
元素A、元素B、元素C:元素列表,无需遵从顺序要求。
例:该DTD并没有对<学生>的子元素的顺序作出要求:


   
   
]>
<学生>
[email protected]
<姓名>张三

下面的DTD片段规定的XML元素是所有的<学生>元素应该有一个<姓名>子元素,同时在此之后还应该有一个<电话>或一个元素,但不能同时有<电话>和两个元素。如:




]>


混合元素类型
这类元素中可以包含子元素,也可以包含纯文本字符,同样也可以在DTD中通过正则表达式规定子元素、纯文本字符出现的顺序和次数。
例:以下<学生>就是一个混合元素,






]>
在定义不同的元素不能使用相同的元素名,即便这些元素的内容、包含的子元素不同也不行。


属性列表声明:
DTD的属性列表声明采用如下格式:

元素缺省值
属性缺省值的意义如下:
#required,表示在标记中必须出现此属性。
#implied,标记中可以不出现此属性。
#fixed,属性是固定的某个值。’
字符串,标记中如没有指定属性的值,那么此字符串就是此属性的值。
必须赋值的属性,关键字REQUIRED说明XML文件中必须为这个属性给出一个属性值。
属性值可有可无的属性,关键字IMPLIED,语法解释其不再强行要求你在XML文件中给该属性赋值。
固定取值的属性,关键字为FIXED,需要为为该属性提供一个缺省值,并且XML文件不会缺省值替代掉。
定义缺省值的属性,如果不使用上面任何一种关键字的话,就是属于这种类型。对于这种属性,你需要在DTD中为它提供一个缺省值,而在XML文件中可以为该属性给出新的属性值来覆盖事先定义的缺省值。
例:
身高 #CDATA#IMPLIED
体重 #CDATA#IMPLIED
联系信息 #CDATA#REQUIRED
政治面貌 #CDATA#FIXED "群众"
家庭出身 #CDATA "独身子女">


属性类型
属性类型主要有10种:
CDATA、ENYMERATED、ID、IDREF、IDREFS、ENTITY、ENTITIES、NMTOKEN、NMTOKENS、NOTATION。
CDATA指的是纯文本,即由字符、符号"&"、小于号<和引号”"“,组成字符串。
属性也可以被描述为一组可接受的取值的列表,XML对属性的赋值将从这个列表中选取一个值。这类属性属于枚举类型,不过关键子ENUMERATED是不出现在DTD定义中的。例:



ID是用属性值的方式为文件中某个元素定义唯一表示的方法。一般而言,不要给ID类型的属性事先指定缺省值。


实体声明
在DTD中,还可以声明一些称为Entity(实体)的东西让DTD和XML文件使用,这就是是实体声明。实体实际上是属性类型的一种,可以吧Entity看作一个常量,它有一定的值,在DTD中,Entity的声明语法为:

引用Entity的时候,必须在Entity名称前加上一个&符号,后面加上";"符号。实体可以分为:内部实体、外部实体和参数实体3种:
内部实体是对文本字符串的命名。如:,此后使用&entity1就相当于插入了字符串"文本"。


外部实体是对其他外部文件的命名,它使得XML文件可以引用外部文件的内容。外部文件可以包含文本,也可以包含二进制数据,与内部实体一样,外部文件将被插入实体引用出现的位置。对于二进制数据的引用通常用来提供图片等非XML的内容。如


与前面两种实体不同,参数实体只能出现于文档类型定义中,包括定义和引用。声明参数实体时,名字前面要加一个%和空格。在引用参数实体时,需要使用%而不是&。参数实体引用将直接展开它所代表的文本,而其他实体引用并不立即展开。


符号声明
和实体声明一样,符号声明也是属性声明的一种,实际就是NOTATION类型。符号声明允许属性值为一个DTD中声明的符号,这个类型对于使用非XML格式的数据非常有用。


要使用NOTATION类型作为属性的类型,首先要在DTD中为可选用的记号作出定义。定义的方式有两种,一种是用MIME类型,形式是

另一种是使用一个URL路径,指定一个处理程序的路径:

例:






]>
<文件>
<视频文件 演示设备="mp"/>



如何使用DTD文件
将DTD与XML联系起来就要用来文档类型声明,文档类型声明必须紧跟XML声明,类型定义信息可以来自外部DTD(称为外部子集),也可直接嵌入XML文档内(称为内部子集),还可以同时提供外部子集和内部子集。使用外部DTD的XML文档的结构为:


文档体....
外部DTD只需将XML声明中的standalone属性声明改为no,然后在文档的第二行加入文档类型声明就ok了。
例:












<书籍>
<名称>.....
<作者>.....
<价格 货币单位="元">35.00<价格>

<书籍>
<名称>....
<作者>....
<价格 货币单位="元">50.00<价格>






4DOM解析器
使用XML标记可以从XML文件中解析出所需要的数据。有两种类型的解析器:基于DOM的解析器和基于事件的解析器。基于DOM的解析器简称为DOM解析器。基于事件的解析器简称SAX解析器。


文档对象模型(DOM)是W3C制定的一套规范标准。DOM规范的核心是按树型结构处理数据。


使用DOM解析器的基本步骤
在JAXP中,DOM解析器是DocumentBuilder类的一个实例,该实例由DocumentBuilderFactory类负责创建,步骤如下:


使用javax.xml.parsers包中的DocumentBuilderFactory类调用其类方法newInstance()实例化一个DocumentBuilderFactory对象。如:
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();


DocumentBuilderFactory对象调用newDocumentBuilder()方法返回一个DocumentBuilder对象。如:
DocumentBuilder builder=factory.newDocumentBuilder();


DocumentBuilder类也在javax.xml.parsers.*包中。


DocumentBuilder类的对象调用public Document parse(File f)方法解析参数f指定的文件,并返回一个实现了Document接口的实例,该实例被称为Document对象。如:
Document document=builder.parse(new File("price.xml));
Document 接口在org.w3c.dom包中import org.w3c.dom.*;。


其他parse方法:
Document parse(InputStream is),将给定 InputStream 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document对象。如:
Document document=builder.parse(new ByteArrayInputStream(字符串.getBytes());


Document parse(String uri),将给定 URI 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。


Document对象
Document对象的结构
Document对象就是一棵树,由实现了Node接口的类的实例组成的树型结构数据,这些实例称为Document对象中的节点。文件中的标记都和Document对象中的某个节点相对应。


Element类、Text类和CDATASection类都是实现了Node接口的类,是比较重要的三个类,这些类的对象分别称作Document对象中的Element节点、Text节点和CDATASection节点。一个Element节点中还可以含有Element节点,Text节点和CDATASection节点。比如Document对象的根节点就是Element类的一个实例,即使一个Element节点。


XML文件中根标记和Document对象中的根节点相对应。Document对象调用getDocumentElement()方法将返回Document对象中的根节点。


Document对象中的重要节点
Element节点
Element节点经常使用下列方法获取和该节点相关的信息:
String getTagName(),返回该节点的名称,该名称就是和此节点相对应的XML中的标记的名称。


String getTextContent(),返回当前节点的文本内容。


String getAttribute(String name),返回该节点中参数name指定的属性的值,该属性值是和此节点对应的XML中的标记中属性的值。


NodeList getChildNodes(),返回一个NodeList对象,该对象由当前节点的子节点组成。


NodeList getElementByTagName(String name)返回一个NodeList对象,该对象由当前节点的Element类型子孙节点组成,这些子孙节点的名字由参数name指定。


boolean hasAttribute(String name),判断当前节点是否有名字由参数name指定的属性。


Text节点
Text节点使用String getWholeText()方法获取节点中的文本。


CDATASection节点
CDATASection节点使用String getWholeText()方法获取节点中的文本,即CDATA端中的文本。


例:
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
    DocumentBuilder builder=factory.newDocumentBuilder();
    Document document=builder.parse(new File("D:\\apache-tomcat-6.0.18\\apache-tomcat-6.0.18\\webapps\\servletTest\\people.xml"));
    Element root=document.getDocumentElement();
    NodeList elementNodes=root.getElementsByTagName("name");
    int size=elementNodes.getLength();
    for(int k=0;k         Node node=elementNodes.item(k);
        if(node.getNodeType()==Node.ELEMENT_NODE){//判断节点的类型
            String password2=((Element)node).getAttribute("password");
            String name2=((Element)node).getAttribute("xingming");
            String nameText=((Element)node).getTextContent();


5SAX解析器
DOM解析器的的核心是在内存中建立和XML文件相对应的树形结构数据。用DOM解析器的好处是:一个应用程序可以方便地操作内存中树的节点来处理XML文档,获取自己所需要的数据。当如果XML文件较大,相应的Document对象就要占用较多的内存空间。


和DOM解析器不同的是,SAX解析器不在内存中建立和XML相对应的树形结构和数据,SAX解析器的核心是事件处理机制。SAX解析器占用的内存较少,


使用SAX解析器的基本步骤
SAX是Simple API for XML的缩写,是JDK1.5提供的解析XML文件的API。SAX解析器是SAXParser类的一个实例,该实例由SAXParseFactory类负责创建。创建SAX解析器的步骤如下:


使用javax.xml.parsers包中的SAXParseFactory类调用其类方法newInstance()实例化一个SAXParserFactory对象。如:
SAXParseFactory factory=SAXParseFactory.newInstance();


SAXParseFactory对象调用newSAXParser()方法返回一个SAXParser对象,称为SAX解析器。如:
SAXParser saparser=factory.newSAXParser();


SAXParser对象调用public void parse(File f,DefaultHandler dh)方法解析参数f指定的XML文件。


SAX解析器的工作原理
SAX解析器调用parse方法解析XML文件,parse方法的第二个参数dh是DefaultHandler类型,称为事件处理器。parse方法在解析XML文件的过程中,根据从文件中解析出的数据产生相应的事件,并报告这个事件给事件处理器dh。处理器dh会根据相应的事件调用相应的方法来处理数据。parse方法必须等待事件处理器处理完毕后才能继续解析文件、报告下一个事件。


事件处理器
DefaultHandler类是org.xml.sax.helpers包中的类,该类或其子类的对象称为解析器的事件处理器。DefaultHandler类实现了ContentHandler、DTDHandler、EntityResolver和ErrorHandler接口。DefaultHandler定义了事件处理器根据相应事件应该调用的方法。


事件的产生与处理
在编写程序时,需要使用DefaultHandler类的子类创建一个事件处理器。当处理器对报告的事件不感兴趣时,就直接调用父类继承的方法,采用默认的处理方式,父类方法的方法体没有具体的处理语句;当处理器对报告的事件感兴趣时,子类就可以重写父类的某些方法,调用重写的方法,以便处理器可以具体地处理解析器报告的数据。


几种重要的事件:
文件开始事件与结束事件
当解析器开始了开始解析XML文件时,就会报告文件开始事件给事件处理器,然后再陆续地报告其他的事件,比如:“开始标记”、“文本事件”等,最后报告“文件结束”事件。解析器报告文件开始事件,事件处理器就会调用startDocument()方法;解析器报告文件结束事件,事件处理器就会调用endDocument()方法。解析器在解析XML文件的过程中只能报告一次文件开始事件和文件结束事件。


开始标记事件与结束标记事件
当解析器发现一个标记的开始标记时,就将所发现的数据封装为一个开始标记事件,并报告该事件给事件处理器,事件处理器调用以下方法对发现的数据做出处理。
startElement(String uri,String localName,String qName,Attributes atts)


atts是解析器发现的标记的全部属性,uri就是解析器发现的标记的名称空间,如果没有名称空间uri值为null、localName是标记的名称、qName是带名称空间前缀的标记名称,如果没有名称空间的前缀则其为标记名称。


事件处理器调用完startElement方法后,将陆续地收到解析器报告的其他事件,比如文本事件、子标记开始事件等,由于XML文件中的标记一定有结束标记,所以对同一个标记,解析器还会报告标记结束的事件。
endElement(String uri,String localName,String gName)


文本数据事件
XML文件中的标记的内容中可以有文本数据,当解析器解析这些数据时,就报告文本数据事件给处理器。事件处理器就会知道所发生的事件,然后调用:
public void characters(char[] ch,int start,int length)
参数字符数组ch中存放的就是解析器解析出的文本数据。start是数组ch中存放字符的起始位置,length是存放的字符的个数。


CSS就是一种叫做样式表的技术,也称之为层叠样式表。CSS是通过对页面结构的风格控制的思想,控制整个页面的风格的。


CSS的基本格式
part{property:value;property:value;...}
part:选择符,被施加样式的元素,可以是标记(tag)、类(class)、标识(id)等。
property:样式属性,可以是颜色、字体、背景等等。
vlaue:样式属性取值,决定样式结果。


对于每个被施加的样式的元素,都采用了命令括号{...}的格式封闭称为一个独立的单元。样式单一般不包含在XML文档内部,而是以独立的文档方式存在,可以通过如下格式在XML文档内部引用CSS风格样式表:

xml-stylesheet为关键字,type="text/css"表示风格样式表为CSS类型。hre="example1.css"表示所引用的风格样式表文件为example1.css,而且该文件与引用它的XML文档位于统一目录下,如果而这不再同一目录下,则必须给出文件的绝对路径。


文字控制
part1{FONT-FAMILY:"宋体";FONT-SIZE:9pt;LINE-HEIGHT:12pt;color:#000000}


链接色彩变化及下划线的控制
A:hover{BACKGOUND-COLOR:#ffccff;COLOR:#0080ff}
hover表示鼠标指示时,链接文字背景色为#ffccff、前景色为#0080ff


A:link{color:#00000;text-decoration:none}
active表示鼠标点击时,链接颜色为绿色,链接无下划线


A:visited{color:gray;text-decoration:none}
visited表示被访问后,链接颜色为灰色,链接无下划线。


A:active{color:green;text-decoration:none}
active表示鼠标点击时,链接颜色为绿色,链接无下划线。


A:hover{text-decoration:underline}
hover表示鼠标指示时,链接显示下划线。
none:没有下划线,underline:下划线,overline:上划线,line-through:中划线。


例:





李超群
雷风雨
1
当代商城

[email protected]
[email protected]
钻石主板2代


朱峰
3
上海市淮海路35号

[email protected]
[email protected]
021-76483218
轻骑兵组合音响




customer.dtd










example1.css:
information,customer
{
font-family:"宋体";
font-size:10.5pt;
font-weight:bold;
color:black;
display:block;
margin-bottom:5pt;
}
id,address,telephone
{
font-family:"宋体";
font-weight:normal;
font-size:10.5pt;
display:block;
color:blue;
margin-left:20pt;
}
name,email
{
font-family:"行楷"
font-weight:bold;
font-size:10.5pt;
display:block;
color:red;
margin-top:5pt;
margin-left:8pt;
}




****************
用SAX方式解析XML,XML文件如下: 
 
 
王小明 
信息学院 
6258113 
男,1955年生,博士,95年调入海南大学 
 


 


事件回调类SAXHandler.java 
import java.io.*; 
import java.util.Hashtable; 
import org.xml.sax.*; 
public class SAXHandler extends HandlerBase 



private Hashtable table = new Hashtable(); 
private String currentElement = null; 
private String currentValue = null; 
public void setTable(Hashtable table) 

this.table = table; 

public Hashtable getTable() 

return table; 

public void startElement(String tag, AttributeList attrs) 
throws SAXException 

currentElement = tag; 

public void characters(char[] ch, int start, int length) 
throws SAXException 

currentValue = new String(ch, start, length); 

public void endElement(String name) throws SAXException 

if (currentElement.equals(name)) 
table.put(currentElement, currentValue); 




 


JSP内容显示源码,SaxXml.jsp: 
 
 
剖析XML文件people.xml 
 
 
<%@ page errorPage="ErrPage.jsp" contentType="text/html;charset=GB2312" %> 
<%@ page import="java.io.*" %> 
<%@ page import="java.util.Hashtable" %> 
<%@ page import="org.w3c.dom.*" %> 
<%@ page import="org.xml.sax.*" %> 
<%@ page import="javax.xml.parsers.SAXParserFactory" %> 
<%@ page import="javax.xml.parsers.SAXParser" %> 
<%@ page import="SAXHandler" %> 
<% 
File file = new File("c:\people.xml"); 
FileReader reader = new FileReader(file); 
Parser parser; 
SAXParserFactory spf = SAXParserFactory.newInstance(); 
SAXParser sp = spf.newSAXParser(); 
SAXHandler handler = new SAXHandler(); 
sp.parse(new InputSource(reader), handler); 
Hashtable hashTable = handler.getTable(); 
out.println(""); 
out.println("" + ""); 
out.println("" + ""); 
out.println("" + ""); 
out.println("" + ""); 
out.println("
教师信息表
姓名" + 
(String)hashTable.get(new String("name")) + "
学院" + 
(String)hashTable.get(new String("college"))+"
电话" + 
(String)hashTable.get(new String("telephone")) + "
备注" + 
(String)hashTable.get(new String("notes")) + "
"); 
%> 
 
 



















































你可能感兴趣的:(jsp)