使用StAX解析XML: 拉式解析和事件

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。

StAX处理XML 1.StAX(The Streaming API for XML),是一种利用拉模式解析(pull-parsing)XML文档的API。StAX 把重点放在流上,它提供了两套处理 XML 的 API:基于指针的 API, 把 XML 文档当做一个标记(或事件)流来处理;允许应用程序检查解析器的状态,获得解析的上一个标记的信息,然后再处理下一个标记,依此类推;另一种较为高级的是基于迭代器的 API,把 XML 作为一系列事件对象来处理,每个对象和应用程序交换 XML 结构的一部分。应用程序根据需要定制解 阅读详情

相关推荐

典!浅谈读写大型XML文件的流式API:StAX

为了克服SAX和DOM所存在的限制,JAXP随后引入了StAX(Streaming API for XML)。StAX巧妙地融合了SAX的事件驱动模型和DOM的编程便利性,实现了对海量XML数据的高性能读写解析。

weixin_50811484的博客 1934

stax解析xml文档的6种方式

stax解析xml文档的方式: 基于光标的查询; 基于迭代模型的查找; 基于过滤器的查找; 基于xpath的查找; 使用 XMLStreamWriter 创建 xml 文档: 通过 Transformer 更新节点信息;

张鹏@记忆碎片 3305

ArcGIS新手必看:HWSD2土壤数据从下载到批量提取TIFF的完整流程

本文详细介绍了ArcGIS中HWSD2土壤数据的完整处理流程,从数据下载、预处理到批量提取TIFF文件。涵盖栅格属性表构建、属性数据连接及性能优化等关键步骤,帮助新手高效掌握HWSD2数据提取技术,提升地理信息数据处理效率。

ll5678的博客 1036

使用 StAX 解析 XML

1、前言 本文大部分摘抄于IBM developerworks(主要是理论),详下面三篇文章,摘抄主要是为了使自己理解更深一点儿,仅当作笔记而已...也是为了以后再次使用时有个参考!摘抄并不全面,原文内容要丰富地多,详见原文。 参考文章: 使用 StAX 解析 XML,第 1 部分: Streaming API for XML (StAX) 简介:http://www.ibm.com/d

竹叶青的专栏 4502

从立创商城到Cadence:手把手教你实现封装格式的精准迁移

本文详细介绍了如何从立创商城获取元器件封装并精准迁移至Cadence Allegro的全流程。通过实战案例MAX31865ATP+T芯片,逐步解析Altium Designer格式转换、Cadence环境配置、封装导入验证等关键步骤,提供常见问题解决方案和效率提升技巧,帮助硬件工程师实现封装格式的高效迁移。

weixin_42519985的博客 217

Stata实战:5步搞定PSM倾向得分匹配(附完整代码与常见报错解决)

本文详细介绍了使用Stata进行PSM(倾向得分匹配)的5步实战流程,包括数据预处理、模型构建、匹配算法选择、匹配质量诊断和结果解释。提供完整代码示例和常见报错解决方案,帮助研究者高效完成实证分析,提升匹配成功率。

weixin_29214559的博客 592

stax解析xml_使用StAX部分解析XML文档

解析XML文档时, XMLEventReader实例通过其next()方法将事件对象传递给客户端应用程序-文档中每个语法单元一个。 但是,应用程序并不总是对接收所有事件类感兴趣。 仅查看XML元素及其属性的应用程序不关心表示注释或处理指令的事件。 幸运的是,StAX允许您通过实现事件过滤器来跳过某些事件类。 清单1显示了一个跳过所有XML处理指令的事件过滤器。 这些事件不会传递给事件读取器...

cuyi7076的博客 609

2026年经典爬虫案例专栏|第17篇:学术论文爬虫实战——知网与万方数据采集

字段名说明数据类型title论文标题字符串authors作者列表列表abstract摘要字符串keywords关键词列表列表journal发表期刊字符串year发表年份整数volume卷号字符串issue期号字符串pages页码范围字符串citations引用次数整数downloads下载次数整数doiDOI编号字符串url论文链接字符串学术论文爬虫是科研工作的重要辅助工具,可以帮助研究人员高效地收集和管理论文数据。

2201_76125261的博客 1064

Resin启动Webservice客户端,调用Webservice服务报property "javax.xml.stream.supportDTD" not supported错误

说明:Webservice客户端是用CXF框架的wsdl2java工具根据wsdl文件生成的,Webservice服务端其他公司使用.net开发的。   首先对生成的java客户端代码写了main方法测试,调用webservice服务正常。 然后我把生成java客户端代码加拷到我现有的Web工程中,然后通过http的方式去调用该客户端代码去调用Webservice服务,结果报错。完整的报错信

rj042的专栏 7994

基于YOLOv8的农作物病虫害检测系统设计与实现

国内如中国农业大学的科研团队采用改进的Faster R-CNN模型对小麦病害进行检测,取得了较好的效果。农作物病虫害是影响农业生产的重要因素之一,每年因病虫害导致的农作物减产高达20%-40%。YOLO(You Only Look Once)系列算法作为目标检测领域的代表性模型,以其高效、准确的特点在众多领域得到广泛应用。YOLOv8作为该系列的最新版本,在精度和速度上都有显著提升,非常适合农作物病虫害检测这类需要实时处理的应用场景。然而,现有研究仍存在一些不足:一是模型复杂度高,难以部署到移动设备;

YOLO 795

FPGA实现AXI-Stream通信

本文介绍了在FPGA中实现AXI-Stream接口的工业级方案,重点解析了核心协议信号(TVALID/TREADY/TDATA/TLAST)与可选扩展信号,并提供了Verilog最小化实现示例。文章详细阐述了握手协议规则、时序约束方法,以及吞吐量优化技巧(如寄存器切片和双缓冲策略),同时给出了跨时钟域处理的异步FIFO解决方案。此外,还包含验证调试方法(Testbench结构和ILA触发设置)和典型应用场景(视频处理/网络传输),最后提供了资源消耗参考数据。该实现方案严格遵循Xilinx/Intel官方规范

whm128的博客 1466

XML入门(四)使用STAX解析XML

前言       本章讲解使用STAX解析XML文件 方法 1.概念 在我们XML解析技术发展的过程中,诞生了很多优秀的解析技术,如:DOM、SAX、JDOM、Dom4J、STAX等 这里我们来讲解一下STAX解析XML文档的方法! 2.使用STAX解析XML 1)准备如下xml文件放在src目录下 &lt;?xml version="1.0" encoding="UTF-8"?...

jwang的博客 1315

NetSuite软件二次开发:NetSuite二次开发最佳实践与案例分析

SuiteScript是NetSuite提供的一种用于二次开发的脚本语言,它基于JavaScript,但添加了特定的API和框架,以支持NetSuite平台的业务逻辑开发。SuiteScript有两种版本:SuiteScript 1.0和SuiteScript 2.0,后者提供了更现代的面向对象编程模型,增强了代码的可读性和可维护性。NetSuite允许用户自定义字段以满足特定的业务需求。这些字段可以添加到现有的记录类型中,也可以用于自定义记录。自定义字段可以是文本、数字、日期、下拉列表等多种类型。

kkchenjj的博客 1468

使用 StAX 解析 XML,第 2 部分: 拉式解析和事件

http://www.ibm.com/developerworks/cn/xml/x-stax2.html 探讨 StAX 基于事件迭代器的 API Peter Nehrer (pnehrer@ecliptical.ca), 自由撰稿人, 独立咨询顾问 简介: Streaming API for XML (StAX) 的基于事件迭代器 AP

achellies's Blog 2544

NL2SQL实践系列(1):深入解析Prompt工程在text2sql中的应用技巧

NL2SQL实践系列(1):深入解析Prompt工程在text2sql中的应用技巧

丨汀、的博客 4328

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

java解析XML 四种技术

转自:http://my.oschina.net/exit/blog/156250 第一种:DOM。  DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问

百川 745

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

StAX-基于流的拉式XML解析

最近在学习webservice时,发现很多框架,技术都在使用StAX作为底层XML解析工具,于是今天看了看资料,学习了下,在这里做个总结。 简介 StAX,全称Streaming API for XML,一种全新的,基于流的JAVA XML解析标准类库。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。在某种程度上来说,StAX

xiongqi215的专栏 1573

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

XML编程总结——使用StAX接口操作xml

使用StAX接口操作xml StAX,全称Streaming API for XML,一种全新的,基于流的JAVA XML解析标准类库。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。在某种程度上来说,StAX与SAX一样是基于XML事件的解析方式,它们都不会一次性加载整个XML文件。但是它们之间也有很大的不同。 StAX和SAX的区别——拉式解析器和推式解析器的区别 虽然StAX与SAX一样基于XML事件解析,相比于DOM将整个XM

David_XM的博客 917

JAVA解析XML(StAX)

HostAliveTask repeat 180 WebpageRespTask repeat 180 AlarmNumTask daily 16:45:00 import global.Global; import java.io.FileInputStream; import java.io.FileNotFoundEx

m_vptr的专栏 3986

XML编程总结——java使用StAX接口操作xml

使用StAX接口操作xml StAX,全称Streaming API for XML,一种全新的,基于流的JAVA XML解析标准类库。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。在某种程度上来说,StAX与SAX一样是基于XML事件的解析方式,它们都不会一次性加载整个XML文件。但是它们之间也有很大的不同。 StAX和S...

HD243608836的博客 579

第一百八十八节 Java XML教程 - Java StAX

第一百八十八节 Java XML教程 - Java StAX

2301_78772942的博客 1585

使用StAX解析器解析大型xml文件

本文大部分摘抄于IBM developerworks(主要是理论),详下面三篇文章,摘抄主要是为了使自己理解更深一点儿,仅当作笔记而已...也是为了以后再次使用时有个参考!摘抄并不全面,原文内容要丰富地多,详见原文。参考文章:使用 StAX 解析 XML,第 1 部分: Streaming API for XML (StAX) 简介:http://www.ibm.com/developerworks/cn/xml/x-stax1.html。

Yinhui0083的博客 1138
上一篇: [转载]Streaming API for XML (StAX) 简介
下一篇: 使用StAX解析XML:使用定制事件和编写 XML
JavaSxy
博客等级 码龄21年 1粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值