Java and XML_读书笔记_2010-05-16

2010-05-16

三、解析XML文档

l  Xerces解析器、SAX类和接口

l  SAX阅读器

n  首先要得到一个符合SAX org.xml.sax.XMLReader接口规范的例子,这个接口定义了解析行为并允许设置某些特征和属性。该接口替换了SAX1.0中的org.xml.sax.Parser

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.XMLReader;
XMLReader parser = new SAXParser();
parser.parse(uri);

n  当一个解析器调入并准备就绪后,它就可以对文档进行解析了,通常由parse()方法的org.xml.sax.XMLReader来处理一个org.xml.sax.InputSource或者一个URI串。

n  内容管理器:在解析进行时,为使应用程序有效地处理XML数据,必须用SAX解析器登记管理器(handler)。管理器是一组SAX定义的回调,它能在文档解析过程中给重要的事件插入相应的应用程序代码。这些事件与文档解析同时进行。SAX成为一个强大接口的原因之一:不需要在起始时就将全部文档读入内存,二十可以对其进行连续处理。

n  SAX2.0定义了四个核心的管理器接口:org.xml.sax.ContentHandlerorg.xml.sax.ErrorHandlerorg.xml.sax.DTDHandlerorg.xml.sax.EntityResolver。解析过程中,执行特定动作的定制应用类支持所有接口,这些执行类可以用SetContentHandler()setDTDHandler()setEntityResolver()的方法在解析器上注册。

u  文档定位器:org.xml.sax.Locator当某回调事件出现时,完成处理的类必须从SAX解析器的XML文档中找到相应的位置。

u  文档的开头和结尾:startDocument()endDocument()
startDocument()
在任何其他回调之前被调用
endDocument()
经常是在所有管理器中最后被调用的放,若不可恢复性错误发生,则ErrorHandler回调方法将被唤醒,同时去调用endDocument()结束此解析过程。
这两个回调方法都会抛出SAXException,这也是SAX事件会抛出异常的唯一方式

u  处理指令:SAX定义了特殊的回调来处理指令。这中方法接受处理指令的目标和那些传递给处理指令的所有数据。

u  名字空间的回调:有两种SAX回调函数专门用于处理名字空间(尽管元素回调也使用它们)。当解析器到底前缀映像(prefix mapping)的开头和结尾时,它们被唤醒
startPrefixMapping()
回调给出与URI相关的名字空间前缀。前缀映像回调在声明名字空间的元素回调之前立即发生。
endPrefixMapping()
回调在声明映像的元素的结束标签之后立即出现

u  元素的回调:事实上超过半数的SAX回调与XML元素属性和数据无任何联系。还有一些SAX回调提供数据的三个基本事件(元素的开始、结束和characters()回调)。此回调的参数为元素的名字(以变量的形式)和一个org.xml.sax.Attributes请求辅助类保留元素中所有属性的指针。Attributes接口可作为元素属性信息的一个广泛的结合来使用。//XML并未要求XML解析器保持属性的顺序

u  元素数据:元素中的文本数据通过characters()回调传递给转换程序的应用程序。这种方法给转换的应用程序提供字符数组,也使开头和结束索引从中读取有关的数据
伪递归(pseudo recursion):元素之间的嵌套导致了回调之间的“嵌套”
这种方法经常导致非常多的混乱,因为SAX接口和标准并未直接定义这个回调如何处理大段的字符数据。characters()方法经常会报告空白,要用到另一个报告空白的SAX回调,ignorableWhitespace()

u  在书写SAX事件管理器时,牢记一个层次的概念。也就是说,不能习惯地认为所有元素都有他们各自的数据和子元素,他们只是作为一个父类而已。还必须牢记,当解析器碰到元素、属性和数据时,他们逐个进行处理,可能会产生一些意外结果。SAX并不做任何预先阅读工作。如果你把XML文档是为一致性数据,请不要做任何认为假设。

u  被忽略的实体:skippedEntity(String name)当实体被未验证解析器忽略时,SAX2.0发出调用来讲该实体忽略。所有的已有的的解析器都不会忽略实体。

u  最后用XMLReader给管理器注册。将由setContentHandler()完成,采用ContentHandler作为其唯一的参数。

n  错误管理器:SAX提供一个能应付解析过程中产生多种ErroHandler接口只定义了三种回调方法error()fatalError()warning()。每个方法从SAXParseException接收出错信息或错误警告信息。每一个错误管理器所接受的都是异常。可以是一个警告,但不会引起解析进程中止,也不会引起一个需解决才能继续解析下去的错误。然而,该回调仍需要执行系统I/O或另一个动作来抛出异常,还必须从应用链中激发。它可通过SAXException()方法来陷入异常。

u  创建一个类,来实现由SAX定义的ErrorHandler接口。为使用传统的错误管理器,需要用SAX解析器注册此错误管理器。由XMLReader接口的setErrorHandler()方法完成。

u  警告:警告语DTD和文档的合法性联系在一起,以后详解。

u  非致命性错误:指解析过程中发生的、可恢复的并且违反了XML规范的错误。
大部分非致命性错误与有效性有关联,以后详解。

u  致命错误:指迫使解析器中止的错误,他们一般与非良构文档有关,导致下面的解析要么是浪费时间,要么在技术性根本不需要。当致命性错误出现时,错误管理器应总能向你或程序管理员报告;在没有干涉的情况下,这些可导致应用程序突然停止。

n  加载解析器的更佳途径

u  原:import org.apache.xerces.parsers.SAXParser;
    import org.xml.sax.XMLReader;
    XMLReader parser = new SAXParser();

u  改: Properties prop = new Properties();

           InputStream inStream =        SAXParserDemo.class.getClassLoader().getResourceAsStream("SaxParser.properties");
            prop.load(inStream);
            XMLReader parser = XMLReaderFactory.createXMLReader(prop.getProperty("SAXParserClassName"));
************SAXParser.propertes************
SAXParserClassName=
org.apache.xerces.parsers.SAXParser

四、约束文档

l  DTD的工作是定义数据如何被格式化。它必须定义XML文档所允许的每个元素、每个属性以及每个元素可能接受的属性值、每个元素的嵌套和时间以及任何可能的外部实体。

n  DTD中指定元素<!ELEMENT [Element Name] [Element Definition /Type]>

u  元素名字要么是名字本身,要么是名字空间前缀和元素名字的组合

u  [Element Definition /Type] DTD中最有用的部分。不论它是纯数据还是含数据和其他元素的复合类型,它都可以通过给定元素的类型,允许在元素中定义数据。

u  嵌套的元素<!ELEMENT [Element Name] [Nested Element] [,Nested Element] ……>
被逗号分开的委员圆括号之间的元素列表时一个元素类型。元素的顺序用来强制性约束XML文档中的元素顺序

u  被解析的数据:文本数据使用的元素类型是#PCDATA。这个关键字表示被解析的字符数据,可用于那些包含文本数据的元素,并且限制元素只能使用文本数据,元素嵌套被禁用

u  空元素:关键字EMPTY约束某元素总为空

u  实体引用(entity reference
<!ENTITY [Element Name] “[Replacement Characters/Identifiers]”>
<!ENTITY [ENTITY Reference] SYSTEM “[URI]”>

URI
可以指向本地文件,也可以是网络资源

u  进一步说明:对元素的最一般的修改操作是一个重现操作符(recurrence operator)。
操作符       |    描述
—— —— —— —— —— —— ——
[Default]   |   
必须出现一次
?               |   
必须出现一次或者根本不出现
+               |   
必须至少出现一次
*               |   
可以出现任何次数,或者根本不出现
每个操作符都被追加在元素的尾部

u  分组(grouping
<!ELEMENT GroupingExample ((Group1El1,Group1EL2),(Group2El1,Group2El2))>

u  or函数:DTD通常提供or函数。用管道操作符来标识or函数
<!ELEMENT AggregateElement (#PCDATA|(Element1,Element2)*)>这样也是有效地,但不鼓励使用这种类型约束。一个元素应该有明确地包含文本数据、被解析的数据,或者其他元素。

n  定义属性:某个属性的出现是否被要求是通过一个关键字指定的。
<!ATTLIST [Enclosing Element]
              [Attribute Name] [Type] [modifier]
               ……………………………

>
通过创建占位符实现属性的添加。DTD要尽可能的自称文档(self-documenting

u  属性类型:对于许多属性而言,属性值可以是文本数据。关键字CDATA表示这种类型,以代表自负数据。同时在XML文档中使用这个关键字表示escape字符数据
属性的下一个类型是枚举类型,如focus属性(Java | XML)

u  modifier#IMPLIED#REQUIRED#FIXED(未指定状态、必须指定、不能修改)
<!ATTLIST [Element Name]
              [Attribute Name] #FIXED [Fixed Value]
               ……………………………
>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值