2020/1/101《XML实用教程》第6章配合XML实用教程例子源代码一起使用Powerpoint制作:耿祥义张跃平基于DOM的解析器2020/1/102本章主要内容•初识DOM解析器•节点类型•Document节点•Element节点•Text节点•CDATASection节点•Attr节点•DocumentType节点•处理空白•使用DOM生成XML文件难点•使用DOM生成XML文件第6章导读2020/1/103概述XML解析器是XML和应用程序之间的一个软件组织,为应用程序从XML文件中解析出所需要的数据。有两种类型的解析器:基于DOM的解析器和基于事件的解析器,本章讲述基于DOM的解析器,下一章讲述基于事件的解析器(SAX)。2020/1/104§6.1初识DOM解析器DOM(DocumentObjectModel,文档对象模型)是W3C制定的一套规范标准,各种语言可以按着DOM规范给出解析XML文件的解析器。Sun公司发布的JDK1.4的后续版本中提供了解析XML文件的API(JavaAPIforXMLParsing,JAXP)。2020/1/105§6.1.1创建DOM解析器的步骤_1在JAXP(JavaAPIforXMLParsing,JAXP)中,DOM解析器是DocumentBuilder类的一个实例,该实例由DocumentBuilderFactory负责创建。步骤有3步。1.使用javax.xml.parsers包中的DocumentBuilderFactory类调用其类方法newInstance()实例化一个DocumentBuilderFactory对象DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();2.factory对象调用newDocumentBuilder()方法返回一个DocumentBuilder对象(DocumentBuilder类在javax.xml.parsers包中)domParser(称做DOM解析器),例如:DocumentBuilderdomParser=factory.newDocumentBuilder();3.domParser对象调用publicDocumentparse(Filef)方法解析参数f指定的XML文件,该方法返回的对象是实现了Document接口的一个实例(Document接口在org.w3c.dom包中),例如:Documentdocument=domParser.parse(newFile(student.xml));2020/1/106§6.1.1创建DOM解析器的步骤_2DOM解析器在内存中建立和XML文件相对应的树形结构数据。应用程序只要分析内存中的树形结构数据,就可以获得XML文件中的各种数据了。2020/1/107§6.1.2Doucument对象的结构在步骤3中,DOM解析器负责在内存中建立Document对象,即调用parse方法返回一个实现Document接口的对象,简称Document对象。也称Document对象为Document节点。应用程序可以从Document节点的子孙节点中获取整个XML文件中数据的细节。Document节点是“树”的根节点,该“树”由实现了Node接口的类的实例所组成,XML文件中的标记都和Document节点的某个Node子节点相对应。例题6-1p1172020/1/108§6.1.2example6_1.xml文件对应的Document节点2020/1/109§6.2.1Node接口§6.2节点的类型Doucumen接口也是Node接口的子接口,也就是说,parse方法将整个被解析的XML文件封装成一个节点返回(XML文件和内存中的Document节点相对应),并且该节点和它的子节点组成树形结构数据。因此,应用程序可以从Document节点的子孙节点中获取整个XML文件中数据的细节。2020/1/1010§6.2.2Node接口的常用方法◆shortgetNodeType()该方法返回一个表示节点类型的常量(Node接口规定的常量值),例如,对于Element节点,getNodeType()方法返回的值为Node.ELEMENT_NODE◆NodeListgetChildNodes()返回一个由当前节点的所有子节点组成的NodeList对象。◆NodegetFirstChild()返回当前节点的第一个子节点。◆NodegetLastChild()返回当前节点的最后一个子节点。◆NodeListgetTextContent()返回当前节点及所有子孙节点中的文本内容。2020/1/1011§6.2.3节点的子孙关系为了解析规范的XML文件,DOM规范规定了各种类型节点之间可以形成的子孙关系,比如,Document节点有且仅有一个Element节点,也可以有一个DocumentType节点(规范的XML文件有且仅有一个根标记,也可以有一个与其关联的DTD文件),Element节点可以有Element子节点和Text子节点(规范的XML文件中的标记可以有子标记和文本)。2020/1/1012§6.2.4使用递归方法输出节点中的数据节点调用getNodeType()方法返回一个表示节点类型的常量(Node接口规定的常量值),因此我们可以通过判断节点的类型来输出和节点相关的数据,比如当节点类型的Element节点时,就输出节点的名字,当节点是Text节点时就输出节点中的数据等。例题6-2p1202020/1/1013§6.3Document节点解析器的parse方法将整个被解析的XML文件封装成一个Document节点返回,应用程序可以从该节点的子孙节点中获取整个XML文件中数据的细节。Document节点的两个直接子节点的类型分别是DocumentType类型和Element类型,其中的DocumentType节点对应着XML文件所关联的DTD文件,通过进一步获取该节点子孙节点来分析DTDL文件中的数据;而其中的Element类型节点对应着XML文件的根节点,通过进一步获取该Element类型节点子孙节点来分析XML文件中的数据。2020/1/1014§6.4Element节点Element节点是Document节点的最重要的子孙节点,因为被解析的XML文件的标记对应着这样类型的节点。表示Element节点的常量是Node.ELEMENT_NODE,一个节点用shortgetNodeType()方法返回的值如果等于Node.ELEMENT_NODE,那么该节点就是Element节点。Element节点经常使用下列方法获取和该节点相关的信•ØStringgetTagName()•ØStringgetAttribute(Stringname)•ØNodeListgetElementsByTagName(Stringname)NodeListgetElementsByTagNameNS(StringnamespaceURI,StringlocalName)。•ØbooleanhasAttribute(Stringname)•booleanhasAttributeNS(StringnamespaceURI,StringlocalName)例题6-3p1222020/1/1015§6.5Text节点规范的XML文件的非空标记可以有子标记和文本内容。在DOM规范中,解析器使用Element节点封装标记,用Text节点封装标记的文本内容,即Element节点可以有Element子节点和Text节点。表示Text节点的常量是Node.TEXT_NODE,一个节点调用shortgetNodeType()方法返回的值如果等于Node.TEXT_NODE,那么该节点就是Text节点。Text节点使用StringgetWholeText()方法获取节点中的文本(包括其中的空白字符)。例题6-4p124,例题6-5p1252020/1/1016§6.6Attr节点在XML文件中,属性并不是标记的子标记,因此,在DOM规范中,Att节点也不是Element节点的子节点。如果想解析XML文件中标记的属性,必须让对应的Element节点调用调用NamedNodeMapgetAttributes()方法。该方法返回的NamedNodeMap对象由有节点组成,这些节点可以被转换为Attr节点。Attr节点通过调用StringgetName()方法返回属性的名字、调用StringgetValue()方法返回属性的值。例题6-6p1272020/1/1017§6.7DocumentType节点DocumentType节点是Document节点的一个子节点。DocumentType节点对应着XML文件所关联的DTD文件,通过进一步获取该节点子孙节点来分析DTD文件中的数据。Document节点调用getDoctype()返回当前节点的DocumentType子节点。例题6-7p1282020/1/1018§6.8处理空白标记之间的缩进区域是为了使得XML文件看起来更美观很形成的,但解析器并不知道这一点,所以解析器仍然认为它们是有用的文本数据(由空白类字符组成,如:\t\n\x0B\f\r)。如果想让DOM解析器忽略缩进空白,即这些缩进空白不在Document中形成Text节点,那么XML文件必须是有效的,而且所关联的DTD文件必须规定XML文件的标记不能有混合内容,同时DocumentBuilderFactory对象在给出DOM解析器之前,必须调用setIgnoringElementContentWhitespace(booleanwhitespace)进行设置,将参数whitespace的的取值为true。例题6-8p1302020/1/1019§6.9验证规范性和有效性JAXP(JavaAPIforXMLParsing)提供的解析器默认地检查XML文件是否是规范的,并不检查XML文件是否是有效的,也就是说,DOM解析器调用parse()方法时,如果XML文件是规范的,parse()方法就返回一个实现了Document接口的对象,否则将显示XML文件中不符合规范的错误信息。即使XML文件关联了一个DTD,解析器也并不检查XML文件是否是有效的,即不检查XML文件是否遵守该DTD规定的限制条件。如果想要检查一个XML文件是否有效,必须让DocumentBuilderFactory对象factory事先设置是否检查XML文件的有效性.如:factory.setValidating(true);2020/1/1020§6.10.1Transformer对象§6.10使用DOM生成XML文件我们可以对Document节点进行修改,然后使用Transformer对象将一个Document节点变换为一个XML文件(Transformer类在javax.xml.transform包中),需要经过如下步骤:1.使用javax.xml.transform包中的TransformerFactory类建立一个对象:TransformerFactorytransFactory=TransformerFactory.newInstance();2.使用步骤1中得到的transFactory对象调用newTransformer()方法得到一个Transformer对象:Transformertransformer=transFactory.newTransformer();3.将被变换的Document对象封装到一个DOMSource对象中(DOMSource类在javax.xml.transform.dom包中):DOMSourcedomSource=newDOMSource(document);4.将变换要得到XML文件对象封装到一个StreamResult对象中(