- 浏览: 309483 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
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虚拟机(开源)
除了提供一个低层的基于指针的 API 之外,StAX 还提供了一个功能强大的基于迭代器的方法,它通过使用事件对象传送关于解析流的信息,以处理 XML。本系列的第 2 部分 详细研究了这种 API 并提供了一些使用它的例子。在本篇文章中,将介绍定制化技术,该技术使用由应用程序定义的事件,您还将看到如何创建定制事件类并使用它们结合基于事件迭代 器的 API 来处理 XML。最后(同样也是重要的一点),将回顾由 StAX 提供的可将 XML 编写为标记流和事件对象的序列化器 API。
当 开发复杂应用程序时,使用分层方法(应用程序的下层为其上层提供必需的抽象)构建应用程序通常会很有用。例如,您可能会将处理 XML 的所有代码集合到一个应用程序提供的高层对象模型。这种技术不仅考虑到通用概念和解决方案的重用,并且还可以加速开发时间和产生更易维护的代码。
因为 StAX 所使用的基于拉的方法将应用程序置于解析过程的控制之下,所以您可以将解析过的事件转换为特定于应用程序的模型对象(例如私有消息或者其他结构的构建 块)。然而,您可能发现继续使用事件会更为方便,这样,您只需在 XML 内容中简单地创建定制事件就可以表示更复杂的结构。通过在底层 XML 数据结构之上叠加定制类型,就可以简化应用程序代码的开发同时允许低层仍然将这些类型作为事件对象处理(例如,将它们作为事件写入一个输出流)。
StAX 事件层次结构是可扩充的。可以扩展已有的事件和定义全新的事件类型。因为事件对象被定义为 Java™ 接口而不是类,因此您可以自由决定如何实现它们。例如,您可以将已有的对象模型分类并且将每一个类型表示为一个事件。您同样可以通过组装、委托等达到相同 的目的。清单 1 显示了一个扩展 Characters
事件来表示特定的数据类型(本例中是一个 Java Date
)的值的例子。所有的子类将文本数据转换为数据值。注意,由于标准事件接口的公共实现不提供 StAX,您可以使用 Decorator
模式包装一个已有的 Characters
实例并向其委托所有的方法调用。
清单 1. 定制 Characters 事件的扩展来表示 Date 值
final DatatypeFactory tf = DatatypeFactory.newInstance(); class DateTime implements Characters { private final Characters d; private final Date value; DateTime(Characters d) { this.d = d; XMLGregorianCalendar cal = tf.newXMLGregorianCalendar(d.getData()); value = cal.toGregorianCalendar().getTime(); } Date getValue() { return value; } public Characters asCharacters() { return d.asCharacters(); } public EndElement asEndElement() { return d.asEndElement(); } public StartElement asStartElement() { return d.asStartElement(); } public String getData() { return d.getData(); } public int getEventType() { return d.getEventType(); } public Location getLocation() { return d.getLocation(); } public QName getSchemaType() { return d.getSchemaType(); } public boolean isAttribute() { return d.isAttribute(); } public boolean isCData() { return d.isCData(); } public boolean isCharacters() { return d.isCharacters(); } public boolean isEndDocument() { return d.isEndDocument(); } public boolean isEndElement() { return d.isEndElement(); } public boolean isEntityReference() { return d.isEntityReference(); } public boolean isIgnorableWhiteSpace() { return d.isIgnorableWhiteSpace(); } public boolean isNamespace() { return d.isNamespace(); } public boolean isProcessingInstruction() { return d.isProcessingInstruction(); } public boolean isStartDocument() { return d.isStartDocument(); } public boolean isStartElement() { return d.isStartElement(); } public boolean isWhiteSpace() { return d.isWhiteSpace(); } public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException { d.writeAsEncodedUnicode(writer); } } |
通常新的事件被完全用来表示特定于应 用程序的 XML 结构。例如,通过一个定制事件类给出某些标记及其属性和/或文本内容,这个类为访问这种数据定义了一个 API(因此就使应用程序从必须使用 XML API 获取数据中解放出来)。即使一个定制事件由几个标准事件复合而成(如 StartElement
、Characters
和 EndElement
),它仍然是一个单独类型的事件,因为它不能被映射到这些事件中的任何一个。
任何定制事件类必须实现 XMLEvent
接口。在 StAX 的当前版本,没有可以通过扩展实现定制事件的抽象基类。幸运的是,您可以在 XMLEvent
中很轻松地实现大部分的方法。例如,向下转型方法(asStartElement()
、asEndElement()
和 asCharacters()
)中的每一个都可以轻易地抛出一个 ClassCastException
(因为这个定制事件不是其中的任何一个)。同样地,布尔查询方法,用于快速决定事件类型(isAttribute()
、isCharacters()
等),可以仅返回 false。如果一个定制事件由其他事件复合而成,getLocation()
方法可仅返回最后一个事件的位置。getSchemaType()
方法可以从相关联的 XML 模式返回外部事件的复合类型的名称。可以编写 writeAsEncodedUnicode(Writer)
方法来依次委派给每一个所包含的事件(例如,对于一个只有简单内容的代表所有元素的定制事件,首先要编写 StartElement
,然后是 Characters
,接着是 EndElement
)。最后,getEventType()
必须返回一个在整个应用程序中表示新事件类型的惟一值。0 到 256 的值被保留下来供 StAX 提供者使用,所以您必须选择这个范围以外的值(并很好地加以说明,这样就不会与整个应用程序中使用的其他定制事件起冲突)。
清单 2 显示了一个定制事件例子,它展现一个 Atom 提要中的图标元素。这个元素由 Atom Syndication Format 规范(1.0 版本)定义,包含了提要的图标的 URL。
清单 2. 展现 Atom 提要图标(只含文本的元素)的定制事件
class Icon implements XMLEvent { private final StartElement startElement; private final String url; private final EndElement endElement; Icon(StartElement startElement, String url, EndElement endElement) { this.startElement = startElement; this.url = url; this.endElement = endElement; } String getURL() { return url; } public Characters asCharacters() { throw new ClassCastException(); } public EndElement asEndElement() { throw new ClassCastException(); } public StartElement asStartElement() { throw new ClassCastException(); } public int getEventType() { return 257; } public Location getLocation() { return endElement.getLocation(); } public QName getSchemaType() { return null; } public boolean isAttribute() { return false; } public boolean isCharacters() { return false; } public boolean isEndDocument() { return false; } public boolean isEndElement() { return false; } public boolean isEntityReference() { return false; } public boolean isNamespace() { return false; } public boolean isProcessingInstruction() { return false; } public boolean isStartDocument() { return false; } public boolean isStartElement() { return false; } public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException { startElement.writeAsEncodedUnicode(writer); ef.createCharacters(url).writeAsEncodedUnicode(writer); endElement.writeAsEncodedUnicode(writer); } } |
到目前为止,您已经了解了如何定义定制事件类,但是还不清楚如何让 StAX 在解析过程中使用它们。接下来的章节介绍将定制事件类插入框架中的技术。
定义一个定制事件后,就可以在事件处理代码中使用它。您可以随意将任意的标准事件序列转化为定制事件(并将它传送给充当事件消费者的其他组件),与将事件转换为一个特定于应用程序对象模型所做的一样。但 StAX 为将定制事件实现插入到框架中提供了一个更通用的机制。
正如您已了解的一样,在逻辑上基于事件迭代器的 API 是基于指针的 API 上面的一层。事实上,XMLEventReader
的一个标准实现可以包装一个 XMLStreamReader
并在其当前状态的基础上创建事件对象。为了支持应用程序定义的事件,当需要创建一个具体事件时,XMLEventReader
使用一个应用程序提供的 XMLEventAllocator
实例,这可以通过 XMLInputFactory
进行设置。要使用一个定制 XMLEventAllocator
,应用程序应该通过调用 XMLInputFactory
的 setEventAllocator(XMLEventAllocator)
方法提供它的一个实例。
XMLEventAllocator
本质上是基于指针的 API 和基于事件迭代器的 API 之间的一座桥梁。除了充当其自身的工厂(XMLInputFactory
为每一个新的 XMLEventReader
实例调用分配器的 newInstance()
方法)之外,该接口还定义了两个事件分配方法。要返回一个表示 stream reader 当前状态的 XMLEvent 需要使用 allocate(XMLStreamReader
)方法,但该方法不能修改 stream reader 的当前状态。这个方法应该主要实现一个指针到事件对象的映射。另一个方法 allocate(XMLStreamReader, XMLEventConsumer)
应使用所提供的 stream reader 来创建一个或更多事件对象并将它们传递给所提供的事件消费者。应用程序在处理过程中可以随意修改 stream reader 的状态;例如,它可以将一个单独的状态分成多个事件对象,或相反地,将几个状态聚结为一个事件(比如通过读取一串标记并将它表示为一个事件对象)。
XMLEventAllocator
的使用是可选的,它没有默认的实例(就是说,默认情况下 XMLEventReader
使用创建事件对象的特定于实现的方法),这样有一些不方便,因为它意味着开发人员不能够扩展已有的分配器(比如通过装饰此分配器)而必须从头开始构建自己的分配器。不过,定制的 XMLEventAllocator
不需要提供每个标准事件类型自己的实现方法。它可以(甚至被鼓励这样做)使用 XMLEventFactory
来实现此目的。
清单 3 显示了一个简单分配器的实现,它将 Atom 提要元素 “published” 和 “updated” 的文本内容转换为一个 DateTime
事件(Characters
事件的扩展)。这些元素只包含文本内容,其文本应该代表一个日期/时间值。这种定制化由 allocate(XMLStreamReader, XMLEventConsumer)
方法执行;当遇到合适的 StartElement
时,所有元素的文本(一直到对应的 EndElement
)都会被转换成单一的 Characters
事件,该事件反过来又由定制 DateTime
事件装饰。结果被馈送给事件消费者。
清单 3. 从元素的文本(其内容代表一个日期/事件值)创建 DateTime 事件的简单事件分配器
final String ATOM_NS = "http://www.w3.org/2005/Atom"; final QName PUBLISHED = new QName(ATOM_NS, "published"); final QName UPDATED = new QName(ATOM_NS, "updated"); final XMLEventFactory ef = XMLEventFactory.newInstance(); class CustomAllocator implements XMLEventAllocator { public XMLEvent allocate(XMLStreamReader r) throws XMLStreamException { switch (r.getEventType()) { case XMLStreamConstants.CDATA: return ef.createCData(r.getText()); case XMLStreamConstants.CHARACTERS: if (r.isWhiteSpace()) return ef.createSpace(r.getText()); return ef.createCharacters(r.getText()); case XMLStreamConstants.COMMENT: return ef.createComment(r.getText()); case XMLStreamConstants.DTD: return ef.createDTD(r.getText()); case XMLStreamConstants.END_DOCUMENT: return ef.createEndDocument(); case XMLStreamConstants.END_ELEMENT: return ef.createEndElement(r.getName(), allocateNamespaces(r)); case XMLStreamConstants.PROCESSING_INSTRUCTION: return ef.createProcessingInstruction(r.getPITarget(), r.getPIData()); case XMLStreamConstants.SPACE: return ef.createIgnorableSpace(r.getText()); case XMLStreamConstants.START_DOCUMENT: String encoding = r.getEncoding(); String version = r.getVersion(); if (encoding != null && version != null && r.standaloneSet()) return ef.createStartDocument(encoding, version, r.isStandalone()); if (encoding != null && version != null) return ef.createStartDocument(encoding, version); if (encoding != null) return ef.createStartDocument(encoding); return ef.createStartDocument(); case XMLStreamConstants.START_ELEMENT: return ef.createStartElement(r.getName(), allocateAttributes(r), allocateNamespaces(r)); default: return null; } } private Iterator allocateNamespaces(XMLStreamReader reader) { ArrayList namespaces = new ArrayList(); for (int i = 0, n = reader.getNamespaceCount(); i < n; ++i) { Namespace namespace; String prefix = reader.getNamespacePrefix(i); String uri = reader.getNamespaceURI(i); if (prefix == null) namespace = ef.createNamespace(uri); else namespace = ef.createNamespace(prefix, uri); namespaces.add(namespace); } return namespaces.iterator(); } private Iterator allocateAttributes(XMLStreamReader r) { ArrayList attributes = new ArrayList(); for (int i = 0, n = r.getAttributeCount(); i < n; ++i) attributes.add(ef.createAttribute(r.getAttributeName(i), r.getAttributeValue(i))); return attributes.iterator(); } public void allocate(XMLStreamReader reader, XMLEventConsumer consumer) throws XMLStreamException { XMLEvent event = allocate(reader); if (event != null) { consumer.add(event); if (event.isStartElement()) { QName name = event.asStartElement().getName(); if (PUBLISHED.equals(name) || UPDATED.equals(name)) { String text = reader.getElementText(); Characters delegate = ef.createCharacters(text); DateTime dateTime = new DateTime(delegate); consumer.add(dateTime); } } } } public XMLEventAllocator newInstance() { return new CustomAllocator(); } }; |
当输入工厂通过定制事件分配器建好之后,从其中创建的每一个事件读取器都将使用它来创建事件对象。应用程序可以像平常一样使用事件读取器,但这些定制事件应能出现在解析过的事件流中(参见清单 4)。
XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setEventAllocator(new CustomAllocator()); XMLEventReader r = factory.createXMLEventReader(uri, input); try { while (r.hasNext()) { XMLEvent event = r.nextEvent(); if (event instanceof DateTime) System.out.println(((DateTime) event).getValue()); } } finally { r.close(); } |
除了可以为 XML 内容创建特定于应用程序的抽象,此方法还可以以更为节省内存的方式使用事件对象。默认情况下,XMLEventReader
将为它返回的每个事件创建一个新的实例。虽然对应用程序来说这可能比较方便 —— 它可以缓存事件,甚至在解析完成之后还可以使用它们 —— 但在资源受限制的环境中或者处理大型 XML 文档时,它可能会带来负面的性能影响。对于不缓存事件对象的应用程序来说,重用每个事件类型的单个实例而不是每次创建一个新的实例(这样很可能会导致频繁 的垃圾收集)可能更有效。
在第一次需要它的时候,这样一个静态的分配器可能会创建事件的每个类型,以后每次只 返回由新的信息更新过的相同实例。但应用程序却必须了解策略的变化并且相应地处理事件。例如,它必须要十分小心不能顺序拉出两个事件,也不能窥视事件,因 为如果这样将丢失先前返回的事件数据。
如 果不讨论 StAX 的序列化支持,任何对 StAX 的介绍都是不完整的。与输入端一样,输出 XML 也有两种 API。第一种是较低层次的 API,StAX 支持将 XML 编写为 底层的标记流而不需要确保输出是格式良好的(就是说,由应用程序负责在正确的时间调用正确的方法)。另一种较高层次的 API 支持将全部事件对象加到输出流中。
不管何种 API,应用程序都必须首先使用 XMLOutputFactory
创建适当的编写器对象 —— 使用低层 API 的 XMLStreamWriter
或使用基于事件对象 API 的 XMLEventWriter
。要获得默认的 XMLOutputFactory
,调用它的静态 getInstance()
方法(就像任何其他的 JAXP 工厂)。
XMLOutputFactory
支持几种类型的输出,这些输出实际上都是与 XMLInputFactory
支持的输入类型相对应的;除了标准的 Java I/O OutputStream
和 Writer
,同样也支持 JAXP Result
。
在 XMLStreamWriter
接口定义的方法和标准的 Java I/O DataOuputStream
中的方法大体相似,只不过前者针对 XML,后者针对的是简单 Java 数据类型。虽然这个编写器不会检查它的输入是否格式良好,但它的确能够确保 CHARACTERS
事件的数据和属性值被正确转义。
要开始编写一个 XML 文档,应用程序首先调用 writeStartDocument
方法的几种重载版本中的一种。其中一种版本具备显式的文档编码和 XML 版本,另一种只有编码,还有一种对编码和 XML 版本(分别为 UTF-8 和 1.0)使用默认值而不设置参数。对于具有文档类型声明(Document Type Declaration,DTD)的文档,应用程序可以调用 writeDTD(String)
并以整个 DTD production 为参数。
writeStartElement
方法的三个版本都可用于编写元素的开始标记。其中一个版本包括前缀、本地名称和名称空间 URI,此版本将前缀绑定到元素的开始标记创建的新的上下文中的名称空间。另一个版本只包含名称空间 URI 和本地名称;这个版本编写没有前缀的元素(假设此名称空间是上下文默认的名称空间)。最后一个版本只包含本地名称,该版本无论默认名称空间如何都会在其内 启动元素。 注意在上述所有情况下,都由用户负责写出名称空间属性(就是说,将一个前缀绑定到 URI 并不写出这个名称空间声明)。
除了这些方法,还有三个对应的 writeEmptyElement
方法用来编写空元素(就是说,不具备单独的关闭标记)。这些方法同时打开和关闭元素。
当编写 XML 元素时,应用程序负责管理它们的名称空间。StAX 为此提供了几种方法。您可以分别使用 setNamespaceContext(NamespaceContext)
和 getNamespaceContext()
设置并检索全部的名称空间上下文。注意设置一个名称空间的上下文不会写出名称空间声明 —— 它仅定义前缀绑定。这些在代码写 START_ELEMENT
事件时会被使用到。setPrefix(String, String)
方法可以在给定的上下文中将一个前缀绑定到名称空间 URI,getPrefix(String)
检索绑定到给定的 URI 的前缀。setDefaultNamespace(String)
可以在当前的上下文中设置默认的名称空间。
为了准确地写出一个名称空间声明,应用程序可以用一个前缀和一个 URI 调用 writeNamespace(String, String)
,或者调用 writeDefaultNamespace(String)
在当前元素上声明默认名称空间。
编写属性类似于编写元素开始标记,只是您必须同时提供属性值。三个 writeAttribute
方法具有与writeStartElement
方法类似的签名(除了为属性值增加的 String
参数)并且就名称空间而言遵循类似的规则。
除非您使用 writeEmptyElement
方法中的一种,否则为了关闭每个元素的开始标记,在它的内容写出后必须调用 writeEndElement()
。
您可以使用 writeCharacters
和 writeCData
方法编写文本内容。后者可以将文本包装在 CDATA 块中。为了更好地使用内存,还提供了 writeCharacters
的一个版本,它包含一个带有偏移量和长度(而不是 String
对象)的 char 缓冲器。
writeEntityRef
、writeProcessingInstruction
和 writeComment
方法可以分别编写实体引用、过程说明和注释。可调用 writeEndDocument()
方法标记文档的末尾。
典型的类似流的输出方法,flush
和 close
,可以分别用来促使编写器将任何缓存的数据写入底层输出和关闭编写器对象。注意关闭方法只释放编写器需要的资源,并不关闭底层的输出。
清单 5. 使用 XMLStreamWriter 编写一个简单的 XHTML 文档
final String XHTML_NS = "http://www.w3.org/1999/xhtml"; XMLOutputFactory f = XMLOutputFactory.newInstance(); XMLStreamWriter w = f.createXMLStreamWriter(System.out); try { w.writeStartDocument(); w.writeCharacters("\n"); w.writeDTD("<!DOCTYPE html " + "PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); w.writeCharacters("\n"); w.writeStartElement(XHTML_NS, "html"); w.writeDefaultNamespace(XHTML_NS); w.writeAttribute("lang", "en"); w.writeCharacters("\n"); w.writeStartElement(XHTML_NS, "head"); w.writeStartElement(XHTML_NS, "title"); w.writeCharacters("Test"); w.writeEndElement(); w.writeEndElement(); w.writeCharacters("\n"); w.writeStartElement(XHTML_NS, "body"); w.writeCharacters("This is a test."); w.writeEndElement(); w.writeEndElement(); w.writeEndDocument(); } finally { w.close(); } |
与低层 API 相比,XMLEventWriter
使用的基于事件对象的序列化器 API 由更少的方法组成。与其对应的输入端 XMLEventReader
一样,这个编写器使用事件对象表示底层 XML InfoSet
的各个部分。典型的应用程序只需使用 add(XMLEvent)
方法就可写出整个文档。add(XMLEventReader)
是一个很方便的方法,用它可以写出从读取器获得的全部事件。使用这个方法,应用程序可以将整个 XML 流的内容有效地输送到另一个 XML 流,而且内容保持不变。
管理名称空间的一组方法和 XMLStreamWriter
中定义的方法是等价的。getNamespaceContext()
和 setNamespaceContext(NamespaceContext)
方法提供了对整个名称空间上下文的访问。setPrefix(String, String)
和 getPrefix(String)
可以分别绑定和获得名称空间的前缀绑定。最后,setDefaultNamespace(String)
方法可以为当前的名称空间上下文设置默认的名称空间。
正如 XMLStreamWriter
一样,该编写器提供了 flush()
和 close()
方法,可分别用于将缓存数据放到底层输出和关闭编写器。
清单 6. 使用 XMLEventWriter 编写一个简单的 XHTML 文档
final String XHTML_NS = "http://www.w3.org/1999/xhtml"; final QName HTML_TAG = new QName(XHTML_NS, "html"); final QName HEAD_TAG = new QName(XHTML_NS, "head"); final QName TITLE_TAG = new QName(XHTML_NS, "title"); final QName BODY_TAG = new QName(XHTML_NS, "body"); XMLOutputFactory f = XMLOutputFactory.newInstance(); XMLEventWriter w = f.createXMLEventWriter(System.out); XMLEventFactory ef = XMLEventFactory.newInstance(); try { w.add(ef.createStartDocument()); w.add(ef.createIgnorableSpace("\n")); w.add(ef.createDTD("<!DOCTYPE html " + "PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">")); w.add(ef.createIgnorableSpace("\n")); w.add(ef.createStartElement(HTML_TAG, null, null)); w.add(ef.createNamespace(XHTML_NS)); w.add(ef.createAttribute("lang", "en")); w.add(ef.createIgnorableSpace("\n")); w.add(ef.createStartElement(HEAD_TAG, null, null)); w.add(ef.createStartElement(TITLE_TAG, null, null)); w.add(ef.createCharacters("Test")); w.add(ef.createEndElement(TITLE_TAG, null)); w.add(ef.createEndElement(HEAD_TAG, null)); w.add(ef.createIgnorableSpace("\n")); w.add(ef.createStartElement(BODY_TAG, null, null)); w.add(ef.createCharacters("This is a test.")); w.add(ef.createEndElement(BODY_TAG, null)); w.add(ef.createEndElement(HTML_TAG, null)); w.add(ef.createEndDocument()); } finally { w.close(); } |
本 系列向您介绍了 StAX 以及如何在一些需要读/写(或两者都需要)XML 的应用程序中使用它。将 XML 流表示为一系列事件对象的做法功能十分强大,可同时提供灵活性和高效性。StAX 将成为 Java Standard Edition 下一版本的一部分,每个 Java 开发人员都会最终使用到它。
发表评论
-
JavaFX1.2的性能貌似有了很大的提升
2009-06-03 09:36 1994Osvaldo Pinali Doederlein's B ... -
Java.next:第二部分——与Java互操作
2008-09-19 23:05 1892原文地址:Java.next #2: Java Inter ... -
Java.next:第一部分——共同点
2008-09-19 13:31 1567原文地址:Java.next: Common Ground ... -
隐式转换:比动态类型更强大?
2008-09-16 18:37 1677本文内容主要来自Implicit Conversions: ... -
澄清:Java中只有按值传递,没有按引用传递!
2008-07-13 22:23 4003前言:在JAVA面试题解惑系列(五)——传了值还是传了引用 ... -
Ruby,Python不能威胁到Java的13个理由
2008-05-28 22:50 1494最近,danielstoner发表了一篇题为13 reas ... -
Java:进化的尽头
2008-05-28 17:45 1315原文地址:http://blog. ... -
《Effective Java》: Joshua Bloch访谈
2008-05-23 00:52 2626原文地址:Effective ... -
JSR 308:Java语言复杂度在恣意增长?
2008-05-20 13:54 1772原帖地址:http://www ... -
Sun能否让Java重振雄风?
2008-05-13 14:42 0原文地址:Can Sun rejuvenate Java? ... -
Groovy, JRuby, Jython, Scala:谁是胜利者?
2008-05-13 00:04 6563原文地址:Groovy, JRuby, Jython, Sca ... -
JAVA比C++更快?
2008-04-08 15:03 2061首先:我必须承认,我取JA ... -
在J2ME中模拟C语言中的文件操作
2008-02-27 00:09 1634最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种 ... -
使用StAX解析XML: 拉式解析和事件
2007-10-08 20:53 33192007 年 7 月 05 日 Streaming API ... -
[转载]Streaming API for XML (StAX) 简介
2007-10-07 13:35 2314Streaming API for XML (StAX) 是用 ... -
使用CookieHandler管理Cookie数据
2007-05-31 23:22 10901前言 : 因为只学过J2SE部分,对JAVA网络编程也不甚了 ... -
浅谈HTTP的无状态性
2007-05-30 01:26 2044HTTP是Hyper Text Transf ... -
用动态代理进行修饰
2007-04-11 16:26 1876动态代理为实 ... -
一种得到代码所在行号的方法
2007-04-02 20:03 3936RT,今天在论坛上看到有人提出这个问题,马上联想 ... -
网络词汇表
2007-04-01 13:33 2004【协议 】--- protocol,指通信双方通信时遵守的一 ...
相关推荐
STAX解析XML的过程是通过事件驱动的,即在解析XML时,解析器会触发一系列事件,如遇到元素开始、元素结束、文本节点等,开发者注册监听这些事件,然后在事件触发时进行相应的处理。相比于DOM(Document Object ...
### 使用StAX进行高效的XML处理 #### 概述 StAX(Streaming API for XML)是一种新的XML解析方式,它提供...无论是对于需要处理大量数据的应用程序还是需要高效解析XML的应用场景,StAX都是一种值得考虑的技术选择。
3. StAX解析器:结合了DOM和SAX的优点,提供了一种流式解析方法,允许程序以读取或写入事件的方式操作XML,既节省内存又保持了编程灵活性。 4. XPath:是一种查询语言,用于在XML文档中查找信息。它可以快速定位到...
3. StAX解析器:StAX是另一种流式解析器,结合了DOM和SAX的优点。它允许程序员通过迭代器按需读取XML元素,既节省内存又具有一定的灵活性。StAX提供了两种模式:XMLStreamReader用于读取,XMLStreamWriter用于写入。...
在源代码中,可能会看到使用Java的`javax.xml.parsers`和`org.w3c.dom`等库进行DOM解析,或者使用`javax.xml.stream`进行StAX解析。对于SAX解析,可能涉及`org.xml.sax`库和自定义的事件处理器。 通过研究这个...
Java解析XML的四种经典方法是XML处理中常用的技术,它们分别是DOM、SAX、StAX和JDOM。每种方法都有其独特的特性和适用场景,下面将详细介绍这四种方法。 1. DOM(Document Object Model)解析: DOM是W3C制定的一种...
- 解析XML文件:使用`XMLReader`的`parse()`方法解析XML文件。 - 处理事件:在事件处理器的`startElement()`、`endElement()`、`characters()`等方法中编写代码,对XML数据进行处理。 3. DOM与SAX比较: - DOM适合...
在Java中,有多种方式可以解析XML文档,包括DOM(Document Object Model)、SAX(Simple API for XML)和StAX(Streaming API for XML)。下面我们将详细探讨这些解析方法以及相关的API。 1. DOM解析器:DOM解析器...
DOM4J是另一个流行的Java XML处理库,提供了灵活的API,支持DOM、SAX和StAX解析方式。它具有强大的XPath支持,易于学习,适合复杂查询,但内存消耗介于DOM和SAX之间。 5. JAXB(Java Architecture for XML Binding...
Java的`javax.xml.stream.XMLInputFactory`和`javax.xml.stream.XMLStreamReader`类用于实现StAX解析。这种方式介于DOM和SAX之间,既避免了DOM的高内存占用,又提供了比SAX更灵活的控制。 4. JDOM: JDOM是Java的一...
本文将深入探讨Java中解析XML的四种主要方法:DOM、SAX、StAX和JAXB。 1. DOM(Document Object Model) DOM是一种基于树形结构的API,它将整个XML文档加载到内存中,形成一个节点树。你可以通过遍历这个树来访问和...
例如,使用DOM解析器创建`DocumentBuilderFactory`,然后获取`DocumentBuilder`解析XML文件,再通过`NodeList`和`Element`接口遍历XML节点,根据需求创建Java对象。 五、优化和注意事项 1. 使用DOM解析大型XML文件...
SAX-Demo_v1.001展示了如何使用SAX解析XML,你需要编写事件处理器来响应这些事件,从而获取和处理XML数据。 总结起来,XML解析方式的选择取决于具体的应用场景和需求。DOM和JDOM适合于小型XML文档,提供方便的树形...
可以通过编写XML文档、创建解析器来处理XML数据,或者利用XML进行数据交换,比如SOAP(Simple Object Access Protocol)或RESTful服务。熟悉这些基本操作后,可以尝试解决更复杂的XML应用场景,如XML数据库、XML网络...
在"Dom4jExample.java"文件中,可能包含了使用DOM4J解析XML的基本步骤: - 加载XML文件:通过`SAXReader`类创建一个读取器实例。 - 解析XML:使用`read()`方法读取XML文档并生成Document对象。 - 遍历和修改XML:...
Java的`javax.xml.stream.XMLInputFactory`和`javax.xml.stream.XMLEventReader`接口用于创建StAX解析器。 4. JDOM: JDOM是一个基于DOM的Java API,它提供了一个与平台无关的方式来创建和操作XML文档,相比标准DOM...
DOM(Document Object Model)是W3C推荐的一种解析XML的标准方法,它将整个XML文档加载到内存中,形成一个树形结构,便于遍历和操作。Java中的`javax.xml.parsers.DocumentBuilderFactory`和`org.w3c.dom.Document`...
在Java中,我们通常使用两种主要的方法来解析XML:Java内置的API(如JAXB、SAX、DOM)和第三方库DOM4j。 首先,让我们详细了解一下Java内置的XML解析方式: 1. **DOM(Document Object Model)解析**:DOM是W3C...
StAX解析器结合了DOM和SAX的优点,它允许开发者以流式方式读写XML,既可以按需处理数据,又不需要一次性加载整个文档。StAX提供了更高效的处理大型XML文档的能力。在Java中,StAX相关的jar包通常是`stax-api.jar`和...
Java解析XML的四种经典方法主要涵盖DOM、SAX、StAX和JDOM这四种方式,每种方法都有其独特的优势和适用场景。 1)DOM(JAXP Crimson 解析器) DOM(Document Object Model)是W3C推荐的一种XML解析标准,它将XML...