|JavaOne2003|Session1195为Java™2平台和Web服务选择正确的XML解析技术郭平Scardina,MarkKarun,KOracle公司|JavaOne2003|Session11952演讲人•郭平,OracleXML拉解析器实现和中间层XML开发的主持人•KKarun,JSR173:XML流API的专家组成员,Oracle®XMLDeveloper’sKit的技术骨干•MarkScardina,Oracle®XMLDeveloper’sKit集团产品经理,XML传教士,Oracle公司XML标准委员会主席|JavaOne2003|Session11953本课程主要目的•介绍新的解析技术——基于流的拉解析(JSR173)•分析不同的解析技术,并学习在Java™应用和Web服务实现中如何选择正确的解析模式|JavaOne2003|Session11954学习目标•搞清SAX、DOM和StAX等解析器的优缺点•能够用不同的解析器编写应用软件•能够为所编写的应用选择正确的解析技术在本课程的最后,你将能够:|JavaOne2003|Session11955内容安排•分析不同的解析技术–XML简单API(SimpleAPIforXML,SAX)–文档对象模型(DocumentObjectModel,DOM)–XML流API(StreamingAPIforXML,StAX)•在JAX-RPC实现中如何运用StAX•总结•问&答|JavaOne2003|Session11956XML(可扩展标识语言)•来自SGML(ISO8879)的简单而灵活的文本格式•可移植,互操作性好,可靠性高•设计目的是为了满足大规模电子出版的需要•在Web上各种数据的交换和B2B交互中发挥着越来越重要的作用•|JavaOne2003|Session11957XML示例:books.xmlcatalogbookid=“101”titleXMLinanutshell/titleauthorElliotteRustyHarold,W.ScottMeans/authorprice39.95/price/bookbookid=“121”titleWhomovedmycheese/titleauthorSpencer,M.D.Johnson,KennethH.Blanchard/authorprice19.95/price/book/catalog|JavaOne2003|Session11958XML解析的含义•输入:原始XML文档•操作:顺序地读取文档–保证句法上的正确性–可选的有效性检查:是否遵从某个数据模型(例如XML模式)•输出:对文档内容和结构的程序访问是一种软件模块:|JavaOne2003|Session11959XML解析器API的选择•文档对象模型(DocumentObjectModel,DOM)•XML简单API(SimpleAPIforXML,SAX)•XML流API(StreamingAPIforXML,StAX),JSR173|JavaOne2003|Session119510文档对象模型(DOM)•允许对XML文档的内容、结构和样式进行动态访问和更新•W3C标准•1998年10月1日发布了DOMLevel1•2000年11月14日发布了DOMLevel2•|JavaOne2003|Session119511DOM结构文档文档类型元素元素元素属性文本文本文本实体参照属性属性元素注释元素文本文本|JavaOne2003|Session119512用于XML解析的Java™API(JAXP)•是一个抽象层,使SAX和DOM解析器成为插件•使应用的解析独立于解析器的实现•开发人员可以在XML处理器之间交换数据,无需改动应用程序代码•标准Java™API(javax.xml.parsers)–SAXParserFactorySAXParser–DocumentBuilderFactoryDocumentBuilder|JavaOne2003|Session119513DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();DocumentBuilderdocumentBuilder=factory.newDocumentBuilder();Documentdocument=documentBuilder.parse(newFile(“books.xml”));NodeListnodes=document.getElementsByTagName(“title”);while(inti=0;inodes.length();i++){ElementtitleElem=(Element)nodes.item(i);NodechildNode=titleElem.getFirstChild();if(childNodeinstanceofText){System.out.println(“Booktitleis:“+childNode.getNodeValue());}}DOM解析示例(使用JAXP)|JavaOne2003|Session119514DOM—优点•为在树中查找或随机访问数据提供了详细的API•提供有可操纵DOM树的API•是一种与平台和语言无关的接口|JavaOne2003|Session119515DOM—缺点•把整个文档加载到内存中–XML文档较大时,给内存造成很大负担,导致性能低下•通用DOM结点类型不适于要求使用强类型的应用•需要一次性地解析整个文档,不允许部分解析|JavaOne2003|Session119516运用DOM的要求•需要细粒度访问XML文档•需要更新或更改XML结构•大多数XSLT处理器都需要|JavaOne2003|Session119517XML简单API(SAX)•基于事件的API,通过回调直接向应用返回解析事件•XML事件模型的已确定标准•1998年5月11日发布SAX1.0•2002年1月29日发布当前版本SAX2.0.1•|JavaOne2003|Session119518SAX事件推模型Books.xmlSAX解析器MyContentHandler读入字符打印书名信息endElement“title”isTitle=falsestartElement“title”isTitle=true推事件|JavaOne2003|Session119519SAXParsersaxParser=SAXParserFactory.newInstance().newSAXParser();saxParser.parse(newFile(“books.xml”),myContentHandler);publicclassMyContentHandlerextendsDefaultHandler{booleanisTitle;publicvoidstartElement(Stringuri,StringlocalName,StringqName,Attributesatts){if(localName.equals(“title”))isTitle=true;}publicvoidendElement(Stringuri,StringlocalName,StringqName){if(localName.equals(“title”))isTitle=false;}publicvoidcharacters(char[]chars,intstart,intlength){if(isTitle)System.out.println(newString(chars,start,length));}}SAX解析示例(使用JAXP)|JavaOne2003|Session119520SAX—优点•效率高,灵活性好,提供对文档的低层次的访问•基于事件的API,不采用内建的树型表示•减少了资源的使用•可以解析大于系统内存的文档|JavaOne2003|Session119521SAX—缺点•需要由应用程序实现对接收到的事件的处理–应用程序必须通过所编写的代码跟踪当前解析状态–编程难度大,特别是当XML文档结构复杂时•整个文档的解析一次完成,无法进行部分解析•不支持导航•不能改动XML文档|JavaOne2003|Session119522运用SAX的要求•针对XML的文档流•从XML文档中获取全部数据•对整个XML文档进行过滤•对XML文档进行DTD或XSD验证|JavaOne2003|Session119523JSR173:XML流API(StAX)•基于事件的XML拉解析API•支持Java友好读入/写出流•很快将公布JSR-173的最后草案•=173|JavaOne2003|Session119524XMLEventStartElementEndElementStartDocumentEndDocument字符处理语句实体参照CDATA注释StAX事件类型|JavaOne2003|Session119525创建读者/写者的工厂•创建读者、写者和事件的工厂(Factories):–javax.xml.stream.XMLInputFactory–javax.xml.stream.XMLOutputFactory–javax.xml.stream.XMLEventFactory•通过静态方法newInstance获得工厂实例•工厂实现的查找遵循与JAXPDocumentBuilderFactory或SAXParserFactory相同的过程|JavaOne2003|Session119526StAX拉模型Books.xmlStAX解析器应用打印书名信息next()字符endElement“title”next()startElement“title”按需读拉事件next()|JavaOne2003|Session119527XMLStreamReaderreader=XMLInputFactory.newInstance().createXMLStreamReader(newFileInputStream(“books.xml”));while(reader.hasNext()){inteventType=reader.next();if(eventType==XMLEvent.START_ELEMENT&&reader.getLocalName().equals(“title”)){reader.next();System.out.println(reader.getText());}}StAX解析示例(使用游标)|JavaOne2003|Session119528StAX解析示例(使用迭代器)XMLEventReadereventReader=XMLInputFactory.newInstance().createXMLEventReader(newFileInputStream(“books.xml”));while(reader.hasNext()){XMLEventevent=reader.next();if(eventinstanceofStartElement&&((StartElement)event).getLocalName().equals(“title”)){System.out.println(((Characters)reader.next()).getData());}}|JavaOne2003|Se