- 浏览: 308218 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
suxiaojack:
15题,就是拿杨辉三角填充空格,答案应该是C(38,19)吧? ...
Project Euler解题汇总 013 ~ 022 -
songhaikang:
这篇文章挺好的,跟着你的步骤很快就可以入门了。非常感谢。
[转贴]Derby入门 —— (1) -
Eastsun:
呵呵,我没有Android的机器,所以兴趣不大
使用Java写的GVmaker虚拟机(开源) -
crapricorn:
那个版本的用不了虚拟键盘啊 呵呵 我们的手机没有实体键盘呀 所 ...
使用Java写的GVmaker虚拟机(开源) -
Eastsun:
crapricorn 写道希望sun侠能做出个android平 ...
使用Java写的GVmaker虚拟机(开源)
2007 年 7 月 05 日
Streaming API for XML (StAX) 的基于事件迭代器 API 无论在性能还是在可用性上都有其他 XML 处理方法所不及的独到之处。第 1 部分介绍了 StAX 并详细讨论了它的基于指针的 API。本文进一步讨论基于事件迭代器 API 及其为 Java™ 开发人员带来的好处。
第 1 部分(请参阅 参考资料 ) 提到,StAX 提供了两种风格的处理 XML 的 API。基于指针的 API 是解析 XML 的低层方法。使用这种方法,应用程序沿着 XML 标记流移动指针,在每一步中检查解析器的状态来了解解析内容的更多信息。这种方法效率很高,特别适用于资源受限的环境。但是,基于指针的 API 不是面向对象的,因而不适合 Java 应用程序,尤其是在代码的可扩展性和可维护性与性能同样重要的企业领域中就更是如此。比方说,多层 Web 服务使用一般组件处理消息信封,而把特定于消息的内容处理(如参数绑定)委托给其他组件完成,这种情况下就能从面向对象的方法中获益。
StAX 提供的另一种风格的 API 以事件对象为中心。和基于指针的 API 一样,这也是一种基于拉的 XML 解析方法:应用程序使用提供的方法从解析器中拉出每个事件,按照需要处理该事件,依此类推,直到流解析完成(或者应用程序决定停止解析)。
事件迭代器 API 的主要接口是 XMLEventReader
。和 XMLStreamReader
相比它的方法要少很多。这是因为 XMLEventReader
用于迭代事件对象流(事实上 XMLEventReader
扩展了 java.util.Iterator
)。关于解析事件的所有信息都封装在事件对象而不是读取器中。
要使用基于事件迭代器的 API,应用程序首先必须从 XMLInputFactory
获得 XMLEventReader
的实例。工厂本身可用标准 JAXP 方法获得,它依靠抽象工厂模式支持可插入的服务提供者。这就使得获取默认的 XMLInputFactory
实现的实例和调用 XMLInputFactory.getInstance()
一样简单,如清单 1 所示。
String uri = "http://www.atomenabled.org/atom.xml"; URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader reader = factory.createXMLEventReader(uri, input); ... |
XMLInputFactory
支持各种可用于创建 XMLEventReader
的输入源。除了 Java I/O 包中的 InputStream
和 Reader
之外,还支持 JAXP Source(来自 TrAX),后者有助于集成 StAX 和 JAXP 的转换 API(TrAX)。最后,还可以从 XMLStreamReader
创建 XMLEventReader
。这种用法可以很好地说明基于事件迭代器的 API 如何堆叠于基于指针的 API 之上。事实上,实现通常要使用其他输入源创建一个 XMLStreamReader
,然后再用它创建 XMLEventReader
。
创建 XMLEventReader
之后,应用程序可用它迭代表示底层 XML 流的 InfoSet
片段的事件。由于接口 XMLEventReader
扩展了 java.util.Iterator
,可以使用标准迭代器方法如 hasNext()
和 next()
。但是请注意,不支持 remove()
方法,如果调用该方法会抛出异常。
XMLEventReader
还提供了一些方便的方法来简化 XML 处理:
-
nextEvent()
本质上是一种等同于 Iterator 的next()
方法的强类型方法,它返回一个XMLEvent
,它是所有事件对象的基本接口。 -
nextTag()
能够跳过所有无关紧要的空白直到下一个开始或结束标记。因此返回值将是StartElement
或EndElement
事件(参见后述)。该方法在处理纯元素(即文档类型声明 DTD 中声明为 EMPTY 的元素)内容时尤其有用。 -
getElementText()
可以访问纯文本元素的文本内容(开始标签到结束标签之间)。从StartElement
作为下一个预期事件开始,该方法在遇到EndElement
之前将所有字符连接起来并返回结果字符串。 -
peek()
可以得到迭代器将返回的下一个事件(如果有)但是不移动迭代器。
清单 2 示范了 XMLEventReader
方法如何用于迭代 Atom 提要。Atom 是用于 Web 发布的一种连锁格式。该例首先获得 XMLInputFactory
的默认实例然后用它创建 XMLEventReader
来解析给定 URL 的 Atom 提要。迭代事件的过程中,peek()
方法判定下一个事件是否从 icon 元素开始,该元素包含提要的图标 URL。如果是,则用 getElementText()
方法获取元素的文本内容(即图标 URL),然后停止迭代。
final QName ICON = new QName("http://www.w3.org/2005/Atom", "icon"); URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader reader = factory.createXMLEventReader(uri, input); try { while (reader.hasNext()) { XMLEvent event = reader.peek(); if (event.isStartElement()) { StartElement start = event.asStartElement(); if (ICON.equals(start.getName())) { System.out.println(reader.getElementText()); break; } } reader.nextEvent(); } } finally { reader.close(); } input.close(); |
返回的事件对象是不变的,应用程序可以保存到解析过程之后。但是应用程序也可定义不同的事件保留(或重用)策略,请参阅第 3 部分。
应用程序也可用 getProperty(String)
从底层实现中获得一个定制的或预先定义的属性值。完成之后,应用程序应该调用读取器的 close()
方法关闭它,以便释放处理所占用的资源。
使用 XMLEventReader
迭代事件流非常简单。处理这些事件需要知道和熟悉 StAX XMLEvent
的层次结构,下面我们来讨论它。
前面已经强调过,XMLEventReader
在解析过程的每一步之后通过事件对象和应用程序通信自己的状态。整个 API 中使用的事件对象的标准类型定义在 javax.xml.stream.events
包中。接口 XMLEvent
表示类型层次结构的根,所有类型的事件必须扩展该接口。表示各种指针层事件类型(在基于指针的 API 中)定义在接口 XMLStreamConstants
中。不过,在第 3 部分将看到也可使用定制的接口(只要扩展了 XMLEvent
)。
从解析器中检索到事件之后,应用程序通常需要将其向下转换成 XMLEvent 的子类型以便访问该特定类型的信息。有多种方法,除了蛮力的 instanceof 检查(即通过一系列的 if/then 语句检查返回的事件是否实现了指定接口)以外,XMLEvent
还提供了 getEventType()
方法返回 XMLStreamConstants
中定义的事件常量。可基于该信息对事件进行向下类型转换。比方说,如果事件的 getEventType()
返回 START_ELEMENT
,它就可以安全地转换成 StartElement
。
确定事件具体类型的另一种方法是使用为此提供的布尔查询方法。比如,如果事件是一个 Attribute 则 isAttribute()
返回 true,如果是 StartElement
则 isStartElement()
返回 true,等等。此外还有几种方便的方法可用于向下类型转换。asStartElement()
、asEndElement()
和 asCharacters()
分别将相应的事件转换成 StartElement
、EndElement
和 Characters
。
清单 3 中首先使用 isStartElement()
和 asStartElement()
方法确定检索的事件是否是 StartElement
,然后将其向下转换成 StartElement
类型,从而访问元素名。
// get an event from the reader ... if (event.isStartElement()) { StartElement start = event.asStartElement(); // use methods provided by StartElement ... |
除了和类型层次结构有关的方法外,XMLEventType
还提供了 getLocation()
、getSchemaType()
和 writeAsEncodedUnicode(Writer)
方法。getLocation()
返回的 Location
对象提供了关于事件在底层输入源中的位置(比如该事件结束的行列号)的可选信息。getSchemaType()
用于检索和给定事件有关的 XML Schema 信息(如果实现支持该功能)。writeAsEncodedUnicode(Writer)
方法以标准的方式定义了将事件对象写入 java.io.Writer
的契约。这些方法对于定义定制的事件(将在下一期讨论)特别有用,因为可以让序列化器委托 XMLEvent
派生类的序列化而不需要应用程序使用定制的序列化器。
解析表示完整 XML 文档的流时,XMLEventReader
返回的第一个事件是 StartDocument
。该接口提供了获得文档本身信息的方法。比如,getSystemId()
方法可以返回文档的系统 ID(如果知道的话)。getVersion()
返回该文档使用的 XML 版本。默认的版本是 1.0,除非在文档的 XML 声明中指定了其他值。
getCharacterEncodingScheme()
返回文档的字符编码,不论在 XML 声明中显式指定还是解析器自动检测。默认值为 UTF-8,除非给出了外部标记声明或者在文档 XML 声明中显式指定了该值,否则 isStandalone()
返回 true。
如果 XMLEventReader
遇到 DTD 则返回 DTD 事件。如果应用程序不关心 DTD,可以通过将解析器的 javax.xml.stream.supportDTD
属性设置为 false 来关闭该特性。事件的 getDocumentTypeDeclaration()
方法可以将整个 DTD 作为一个字符串检索,包括内部子集。这个实现实际上可将 DTD 处理成更加结构化的形式(特定于提供的)并通过调用 getProcessedDTD()
方法使其可用。getEntities()
方法返回 EntityDeclaration
事件列表(参见后述),这些事件表示一般外部实体声明,包括内部和外部实体。此外,getNotations()
方法返回 NotationDeclaration
事件列表(同样将在后面说明),用于表示声明的符号。
EntityDeclaration
事件表示在文档的 DTD 中声明的非解析的一般实体。该事件不被单独报告,而是作为 DTD 事件的一部分。它提供了用于获取实体的名称、公共和系统 ID 以及相关的符号名的方法(分别使用 getName()
、getPublicId()
、getSystemId()
和 getNotationName()
)。如果是内部实体,getReplacementText()
方法可检索其替换文本。
类似的,NotationDeclaration
事件也只能通过 DTD 事件访问。它表示符号声明。除了名称以外(getName()
方法),该接口还提供了检索符号的公共和系统 ID 的方法(分别是 getPublicId()
和 getSystemId()
)。两者至少要有一个可用。
清单 4 示范了如何处理非解析外部实体引用。该例中,虚构的 catalog 文档包含了对内容放在 PDF 或 HTML 文件(两者都不是有效的 XML)的出版物的引用。迭代这些事件的过程中,从 DTD 事件中提取符号声明并按照名字缓存。遇到实体引用时,取得实体声明并根据名称检索缓存的符号声明。实际的应用程序可能会使用符号标识符来定位适当的内容处 理程序并使用实体的系统标识符作为其输入。
final String xml = "<?xml version=\"1.0\" standalone=\"no\" ?>" + "<!DOCTYPE catalog [" + "<!ELEMENT catalog (publication+) >" + "<!ELEMENT publication (#PCDATA) >" + "<!ATTLIST publication title CDATA #REQUIRED >" + "<!NOTATION pdf SYSTEM \"application/pdf\" >" + "<!NOTATION html SYSTEM \"text/html\" >" + "<!ENTITY overview SYSTEM \"resources/overview.pdf\" NDATA pdf >" + "<!ENTITY chapter1 SYSTEM \"resources/chapter_1.html\" NDATA html >" + "]>" + "<catalog>" + "<ext title=\"Overview\">&overview;</ext>" + "<ext title=\"Chapter 1\">&chapter1;</ext>" + "</catalog>"; Map notations = new HashMap(); StringReader input = new StringReader(xml); XMLInputFactory f = XMLInputFactory.newInstance(); XMLEventReader r = f.createXMLEventReader("http://example.com/catalog.xml", input); PrintWriter out = new PrintWriter(System.out); try { while (r.hasNext()) { XMLEvent event = r.nextEvent(); switch (event.getEventType()) { case XMLStreamConstants.ENTITY_REFERENCE: EntityReference ref = (EntityReference) event; EntityDeclaration decl = ref.getDeclaration(); NotationDeclaration n = (NotationDeclaration) notations.get(decl.getNotationName()); out.print("Object of type "); out.print(n.getSystemId()); out.print(" located at "); out.print(decl.getSystemId()); out.print(" would be placed here."); break; case XMLStreamConstants.DTD: DTD dtd = (DTD) event; for (Iterator i = dtd.getNotations().iterator(); i.hasNext();) { n = (NotationDeclaration) i.next(); notations.put(n.getName(), n); } default: event.writeAsEncodedUnicode(out); out.println(); } } } finally { r.close(); } input.close(); out.flush(); |
对每个元素,XMLEventReader
都返回 StartElement
事件表示其开始标记,最后还有对应的 EndElement
事件表示结束标记。即使没有单独的开始和结束标记的空元素(比如 ),读取器也会在 StartElement
之后接着返回 EndElement
事件。
和其他事件相比可能会经常处理 StartElement
,因为它通常用于表示 XML 文档的大部分信息。检索元素的限定名可调用 getName()
。类 QName 表示 XML 限定名,它将限定名中的所有成分(如名称空间 URI、前缀和本地名)封装起来。getNamespaceContext()
方法可以检索当前的名称空间上下文,包括当前所有名称空间的信息。检索元素的属性使用 getAttributes() 或者用 getAttributeByName(QName) 按属性名逐个检索(如果事先知道的话)。类似的,可以调用 getNamespaces()
获得元素上声明的任何名称空间。getNamespaceURI(String)
返回捆绑到当前上下文中特定前缀的名称空间。
虽 然被建模为事件并用接口 Attribute 表示,但元素的属性一般不作为单独的事件报告。而是通过 StartElement 事件访问。getName() 方法返回属性的限定名,getValue() 用字符串返回属性值。调用 isSpecified() 确定元素中是否指定了该属性,或者文档模式提供了默认值。方法 getDTDType() 返回属性的声明类型(如 CDATA、IDREF 或 NMTOKEN)。
类似的,元素中声明的所有名称空间都可通过 StartElement
事件访问而不需要单独报告。接口 Namespace 实际上是扩展了 Attribute,因为名称空间事实上被指定为元素的属性(包括特定的前缀)。方法 getPrefix()
是获得名称空间属性的本地名的快捷方式(除非是默认名称空间声明,这种情况下前缀是一个空字符串而非 “xmlns”)。与此类似,getNamespaceURI()
方法返回属性值(即名称空间 URI)。为了判断该名称空间是否是默认名称空间(具有空前缀),可调用 isDefaultNamespaceDeclaration()
。
EndElement
表示元素的结束标记(或元素标记的结束,如果是空元素的话)。可使用 getName()
方法获取元素的限定名,使用 getNamespaces()
确定那些名称空间超出了作用域。
清单 5 报告所有的 Atom 扩展元素和属性(即不属于 Atom 名称空间或 XML 名称空间的元素和属性)。对每个 StartElement
事件都检查其名称空间 URI 是否是 Atom 名称空间 URI。然后迭代所有的属性,使用 Attribute
接口获得属性名。最后报告不属于 Atom 或 XML 名称空间的属性。
final String ATOM_NS = "http://www.w3.org/2005/Atom"; URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory f = XMLInputFactory.newInstance(); XMLEventReader r = f.createXMLEventReader(uri, input); try { while (r.hasNext()) { XMLEvent event = r.nextEvent(); if (event.isStartElement()) { StartElement start = event.asStartElement(); boolean isExtension = false; boolean elementPrinted = false; if (!ATOM_NS.equals(start.getName().getNamespaceURI())) { System.out.println(start.getName()); isExtension = true; elementPrinted = true; } for (Iterator i = start.getAttributes(); i.hasNext();) { Attribute attr = (Attribute) i.next(); String ns = attr.getName().getNamespaceURI(); if (ATOM_NS.equals(ns)) continue; if ("".equals(ns) && !isExtension) continue; if ("xml".equals(attr.getName().getPrefix())) continue; if (!elementPrinted) { elementPrinted = true; System.out.println(start.getName()); } System.out.print("\t"); System.out.println(attr); } } } } finally { r.close(); } input.close(); |
Characters
事件实际上用于表示三类文本事件:实际内容的文本(CHARACTERS
)、CDATA
部分以及可忽略的空白(SPACE
)。它提供了区分这三种文本类型的方法,如果是 CDATA 事件则 isCData()
返回 true,如果是 SAPCE 事件则 isIgnorableWhitespace()
返回 true。getData()
方法返回该事件的文本。此外,isWhiteSpace()
说明文本是否全部由空白字符组成(不一定是可忽略的空白)。
未解析的一般实体引用由 EntityReference
事件报告。只有当读取器的 javax.xml.stream.isReplacingEntityReferences
属性设为 false 时才会报告解析实体。否则,就要求解析器用替换文本(在声明中做了指定)代替内部实体引用并作为一般字符事件报告,如果是解析的外部实体则作为正常标记报告。接口 EntityReference
提供了获取实体名及其声明的方法(作为 EntityDeclaration
事件),即通过分别调用 getName()
和 getDeclaration()
。
事件 PROCESSING_INSTRUCTION
和 COMMENTS
分别用 ProcessingInstruction
和 Comment
表示。ProcessingInstruction
提供了 getTarget()
和 getData()
方法,用来检索指令的目标和数据。接口 Comment
定义的 getText()
方法可以检索注释文本。
清单 6 中的例子说明了如何使用 Characters 事件报告各种类型的文本内容。同时也说明了接口 Comment 和 ProcessingInstruction 的用法。
final String ATOM_NS = "http://www.w3.org/2005/Atom"; URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory f = XMLInputFactory.newInstance(); XMLEventReader r = f.createXMLEventReader(uri, input); try { while (r.hasNext()) { XMLEvent event = r.nextEvent(); if (event.isCharacters()) { Characters c = event.asCharacters(); System.out.print("Characters"); if (c.isCData()) { System.out.print(" (CDATA):"); System.out.println(c.getData()); } else if (c.isIgnorableWhiteSpace()) { System.out.println(" (IGNORABLE SPACE)"); } else if (c.isWhiteSpace()) { System.out.println(" (EMPTY SPACE)"); } else { System.out.print(": "); System.out.println(c.getData()); } } else if (event.isProcessingInstruction()) { ProcessingInstruction pi = (ProcessingInstruction) event; System.out.print("PI("); System.out.print(pi.getTarget()); System.out.print(", "); System.out.print(pi.getData()); System.out.println(")"); } else if (event.getEventType() == XMLStreamConstants.COMMENT) { System.out.print("Comment: "); System.out.println(((Comment) event).getText()); } } } finally { r.close(); } input.close(); |
XMLEventReader
提交的最后一个事件是 EndDocument
,它没有定义新方法。
可以看到,使用 XMLEventReader
与 XMLEvent
及其子类型解析 XML 非常简单。通过控制解析过程,应用程序可以决定对每个事件做什么。但是如果应用程序(或某个组件)需要特定内容类型的事件流,也可以创建专门的事件读取器。比方说,很容易创建筛选过的 XMLEventStream
只允许特定的事件传递给调用者。只需要对 XMLInputFactory
实例调用 createXMLEventReader(XMLEventReader, EventFilter)
方法,并传递基本事件读取器和接受/拒绝从基本读取器获得的事件的简单筛选器。清单 7 给出了一个筛选器的例子(只接受处理指令事件,应用程序可以定义任何接受条件)。
URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader r = factory.createXMLEventReader(uri, input); XMLEventReader fr = factory.createFilteredReader(r, new EventFilter() { public boolean accept(XMLEvent e) { return e.getEventType() == PROCESSING_INSTRUCTION; } }); try { while (fr.hasNext()) { XMLEvent e = fr.nextEvent(); if (e.getEventType() == PROCESSING_INSTRUCTION) { ProcessingInstruction pi = (ProcessingInstruction) e; System.out.println(pi.getTarget() + ": " + pi.getData()); } } } finally { fr.close(); r.close(); } input.close(); |
要执行更复杂的流操作,可扩展 EventReaderDelegate
,这是 javax.xml.stream.util
包中定义的一个工具类。该类允许开发人员包装已有的 XMLEventStream
,把所有调用都默认委托给它。然后让子类改写某些特殊的方法从而改变基本读取器的行为。比如,可通过该方法在事件流中插入合成事件或者转换它。迭代修改过的流的应用程序不需要知道它处理的是什么。清单 8 给出了使用这种技术的一个例子。
URL url = new URL(uri); InputStream input = url.openStream(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader r = factory.createXMLEventReader(uri, input); XMLEventReader fr = new EventReaderDelegate(r) { private Comment comment; public XMLEvent nextEvent() throws XMLStreamException { XMLEvent event = null; if (comment != null) { event = comment; comment = null; return event; } event = super.nextEvent(); if (event.isStartDocument()) { XMLEventFactory ef = XMLEventFactory.newInstance(); comment = ef.createComment("Generated " + new Date()); } return event; } }; OutputStreamWriter writer = new OutputStreamWriter(System.out); try { while (fr.hasNext()) { XMLEvent event = fr.nextEvent(); event.writeAsEncodedUnicode(writer); } } finally { fr.close(); r.close(); } input.close(); writer.flush(); |
请注意,要实现该例应用程序必须能够创建标准事件的实例(这里是 Comment)。这种功能要用到类 XMLEventFactory
,它定义了各种标准事件类型的创建方法(事实上每个方法都有数个重载版本,根据事件的类型具有不同的参数设置)。和 XMLInputFactory
类似,该类也实现了抽象工厂模式:调用 getInstance()
获得它的具体实例。
本文仅介绍了用 StAX 基于事件迭代器的 API 所能完成的一部分功能,见证了它的灵活性以及易用性。第 3 部分中将介绍如何创建和使用定制事件。还将探究 StAX 序列化器 API。
发表评论
-
JavaFX1.2的性能貌似有了很大的提升
2009-06-03 09:36 1981Osvaldo Pinali Doederlein's B ... -
Java.next:第二部分——与Java互操作
2008-09-19 23:05 1875原文地址:Java.next #2: Java Inter ... -
Java.next:第一部分——共同点
2008-09-19 13:31 1540原文地址:Java.next: Common Ground ... -
隐式转换:比动态类型更强大?
2008-09-16 18:37 1671本文内容主要来自Implicit Conversions: ... -
澄清:Java中只有按值传递,没有按引用传递!
2008-07-13 22:23 3982前言:在JAVA面试题解惑系列(五)——传了值还是传了引用 ... -
Ruby,Python不能威胁到Java的13个理由
2008-05-28 22:50 1481最近,danielstoner发表了一篇题为13 reas ... -
Java:进化的尽头
2008-05-28 17:45 1304原文地址:http://blog. ... -
《Effective Java》: Joshua Bloch访谈
2008-05-23 00:52 2613原文地址:Effective ... -
JSR 308:Java语言复杂度在恣意增长?
2008-05-20 13:54 1759原帖地址:http://www ... -
Sun能否让Java重振雄风?
2008-05-13 14:42 0原文地址:Can Sun rejuvenate Java? ... -
Groovy, JRuby, Jython, Scala:谁是胜利者?
2008-05-13 00:04 6556原文地址:Groovy, JRuby, Jython, Sca ... -
JAVA比C++更快?
2008-04-08 15:03 2043首先:我必须承认,我取JA ... -
在J2ME中模拟C语言中的文件操作
2008-02-27 00:09 1615最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种 ... -
使用StAX解析XML:使用定制事件和编写 XML
2007-10-12 23:01 2103除了提供一个低层的基 ... -
[转载]Streaming API for XML (StAX) 简介
2007-10-07 13:35 2306Streaming API for XML (StAX) 是用 ... -
使用CookieHandler管理Cookie数据
2007-05-31 23:22 10885前言 : 因为只学过J2SE部分,对JAVA网络编程也不甚了 ... -
浅谈HTTP的无状态性
2007-05-30 01:26 2033HTTP是Hyper Text Transf ... -
用动态代理进行修饰
2007-04-11 16:26 1847动态代理为实 ... -
一种得到代码所在行号的方法
2007-04-02 20:03 3919RT,今天在论坛上看到有人提出这个问题,马上联想 ... -
网络词汇表
2007-04-01 13:33 1996【协议 】--- protocol,指通信双方通信时遵守的一 ...
相关推荐
STAX解析XML的过程是通过事件驱动的,即在解析XML时,解析器会触发一系列事件,如遇到元素开始、元素结束、文本节点等,开发者注册监听这些事件,然后在事件触发时进行相应的处理。相比于DOM(Document Object ...
使用StAX解析XML文档则需要借助`XMLInputFactory`和`XMLStreamReader`类完成。下面是一个简单的例子: ```java XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader reader = factory....
首先,使用StAX逐个读取XML事件,然后利用JAXB将这些事件转换为Java对象,从而实现高效且内存友好的XML解析。 下面是一些关键知识点: 1. **StAX解析流程**: - 创建XMLInputFactory实例,这是解析XML的起点。 -...
这个JAR文件提供了实际的XML解析器和生成器,如`XMLInputFactory`和`XMLOutputFactory`,开发者可以使用它们来创建`XMLStreamReader`和`XMLStreamWriter`实例,从而进行XML的读写操作。 在实际开发中,使用STAX时,...
kettle 解析xml数据,xml多层分组嵌套,xml stax方法,完整解析案例使用(包含xml文件以及ktr文件)。ETL大数据迁移,数据清洗。XML Input Stream (StAX) 方法
与上一个版本一起使用可以可以起到提高效率的目的。本人解析xml的真实文档
- Java的SAX解析:使用`org.xml.sax.XMLReader`和`org.xml.sax.helpers.DefaultHandler`处理事件。 - Java的StAX解析:使用`javax.xml.stream.XMLInputFactory`和`javax.xml.stream.XMLStreamReader`进行迭代读取...
- **灵活性**:STAX API设计灵活,支持自定义事件处理器,使得开发者可以根据具体需求定制XML解析和生成行为。 总之,“stax-api-1.0-2”是一个包含源代码、运行时库和Maven配置的STAX API版本,它为Java开发者提供...
STAX的核心理念是事件驱动,即解析XML时,每遇到一个XML元素或属性,都会触发一个相应的事件,程序通过响应这些事件来处理XML数据。与DOM(Document Object Model)不同,STAX不需要一次性加载整个XML文档到内存,...
可以考虑使用SAX或者StAX解析器,它们是事件驱动的,只在需要时处理XML数据,减少内存占用。 5. **安全性**: - 防止SQL注入:使用预编译的`PreparedStatement`可以避免SQL注入攻击,确保参数安全。 - 输入验证:...
本篇文章将深入探讨如何使用JDOM解析XML文件。 首先,我们需要理解JDOM的基本结构。JDOM通过Document对象表示整个XML文档,Element代表XML元素,Attribute表示元素属性,Text表示元素内的文本内容。这些类构成了...
为了使用XML解析支持库,开发者需要了解库的API文档,学习如何初始化解析器、设置事件处理器(对于SAX和StAX),以及如何通过API进行XML操作。此外,良好的错误处理机制也是必不可少的,以应对XML解析过程中可能出现...
StAX(Streaming API for XML)是一种新的XML解析方式,它提供了一种高效的、基于事件驱动的方式来处理XML文档。相比于DOM(Document Object Model)和SAX(Simple API for XML),StAX在处理大型或复杂XML文档时...
Axis2在性能上的提升也得益于采用StAX解析XML。 总之,StAX提供了一种高效、低内存开销的方式来处理XML,尤其适用于处理大型XML文档和需要高性能的应用场景。通过组装和解析XML,开发人员可以灵活地在应用程序之间...
Java作为一种广泛使用的后端编程语言,提供了多种方式来解析XML文档,使得处理多级嵌套的数据变得可能。本文将详细讲解如何在Java中解析XML,特别是针对多级结构的情况。 首先,Java提供了两种主要的API来处理XML:...
2. 使用StAX解析XML: StAX允许程序以迭代方式处理XML,可以逐个读取事件,如下所示: ```java import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream....
下面将详细介绍这四种解析XML的方法。 1. SAX(Simple API for XML) SAX是一种事件驱动的解析器,它不会一次性加载整个XML文档到内存中,而是逐行读取,当遇到文档中的元素、属性等时,会触发相应的事件处理器方法...
如果内存资源有限或文件过大,可以考虑使用 SAX 或者 StAX 解析器,它们是基于事件驱动的,只在需要时读取数据,从而降低了内存需求。 至于"AndroidDomXml"这个文件名,可能是一个 Android 平台上的 XML 解析示例。...
在源代码中,可能会看到使用Java的`javax.xml.parsers`和`org.w3c.dom`等库进行DOM解析,或者使用`javax.xml.stream`进行StAX解析。对于SAX解析,可能涉及`org.xml.sax`库和自定义的事件处理器。 通过研究这个...