`

解析xml时遇到的一些问题

    博客分类:
  • J2SE
 
阅读更多
解析xml时遇到的一些问题
先感谢同事renial的<解析xml时遇到的一些问题>技术分享,下面是一些记录和实际操作

1.使用Dom4j解析大文件时内存溢出的问题

问题是这样的,当我用dom4j去解析一个几十M的xml时,就出现out of memory.当然了,这也是根据你的机器性能而定的,我们都知道dom4j在各种DOM解析器中应该算是性能最好的,连大名鼎鼎的Hibernate都是用dom4j来解析XML配置文件的
问题出在于使用dom4j的SAXReader是会把整个XML文件一次性读入,如果XML文件过大就会抛出out of memory,但即使是使用SAXParser批量读入解析,但它也是一次解析完,假设XML文件有几万条数据,那么解析后就必须在内存放入这几万条对象.

常用的Dom4j文件解析方式:

InputStream is = new FileInputStream(filePath);
SAXReader reader = new SAXReader();  //将整个XML构建为一个Document
Document doc = reader.read(is);
Element root = doc.getRootElement(); // 获得根节点
for (Object obj : root.elements()) { // 遍历每个节点
Element e = (Element)obj;            // 对当前节点进行操作
}

解决方法:使用ElementHandler解析文件

通过查API可以发现ElementHandler接口,下面是接口的介绍

ElementHandler interface defines a handler of Element objects. It is used primarily in event based processing models such as for
processing large XML documents as they are being parsed rather than waiting until the whole document is parsed.

好了,它就是我们想要的,通过实现以下两个method,就可以达成我们的需求

onEnd(ElementPath elementPath)
          Called by an event based processor when an elements closing tag is encountered.
onStart(ElementPath elementPath)
          Called by an event based processor when an elements openning tag is encountered.

下面是代码

FileInputStream fis = new FileInputStream(addPath);
SAXReader reader = new SAXReader();
ElementHandler addHandler = new MyElementHandler();  //建立 MyElementHandler 的实例
reader.addHandler("/root/test1", addHandler); // 节点
reader.addHandler("/root/test2", addHandler); // 节点
reader.read(fis);

...

class MyElementHandler implements ElementHandler {
  public void onStart(ElementPath ep) {}
 
  public void onEnd(ElementPath ep) {
    Element e = ep.getCurrent(); // 获得当前节点
    // 对节点进行操作。。。
    e.detach(); // 处理完当前节点后,将其从dom树中剪除
  }
}

因为每次处理完一个节点后并没有保存在dom树中,所以不会出现内存溢出的情况
上面的省略了一些业务代码,不知道你是否明白或有更好的方法,可以和我联系QQ:34174409

2.BOM头问题

使用java.io.Reader读取XML文件进行解析时出现异常
org.dom4j.DocumentException: Error on line 1 of document : Content is not allowed in prolog.
Nested exception:
org.xml.sax.SAXParseException: Content is not allowed in prolog.
原因在于:UTF-8编码文件存在BOM头,Reader类无法正确识别

解决方法:
(1).使用16进制编辑器手动删除BOM头

这个...自行解决

(2).InputStream读取流中前面的字符,看是否有BOM,如果有BOM,干掉BOM头

PushbackInputStream pis = new PushbackInputStream(in);
int ch = pis.read();
if (ch != 0xEF){
     testin.unread(ch);
} else if ((ch = pis.read()) != 0xBB){
     pis.unread(ch);
     pis.unread(0xef);
} else if ((ch = pis.read()) != 0xBF){
     throw new IOException("wrong format");
} else
{
}

(3).InputStream读取完文件,干掉BOM头

FileInputStream fin = new FileInputStream(fileName);
//写入临时文件
InputStream in = getInputStream(fin);
String tmpFileName = fileName + ".tmp";
FileOutputStream out = new FileOutputStream(tmpFileName);
byte b[] = new byte[4096];

int len = 0;
while (in.available() > 0){
     len = in.read(b, 0, 4096);
     out.write(b, 0, len);
}
in.close();
fin.close();
out.close();

//临时文件写完,开始将临时文件写回本文件。
in = new FileInputStream(tmpFileName);
System.out.println("[" + fileName + "]");
out = new FileOutputStream(fileName);

while (in.available() > 0){
     len = in.read(b, 0, 4096);
     out.write(b, 0, len);
}
in.close();
out.close();

(3).非法XML字符串

解析XML文件时出现非法字符的Exception(即使该字符位于CDATA段内):    org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xb) was found in the CDATA section.
原因在于:根据W3C标准,有一些字符不能出现在XML文件中:
    0x00 - 0x08
    0x0b - 0x0c
    0x0e - 0x1f
解析XML时遇到这些字符就会出错

解决方法:
对有可能出问题的XML文件,进行字符过滤后再进行解析。

public static String stripNonValidXMLChars(String str) {
  if (str == null || "".equals(str)) {
    return str;
  }
  return str.replaceAll("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", "");
}

http://www.blogjava.net/dongbule/archive/2010/09/28/333262.html
----------------------------------------

by 陈于喆
QQ:34174409
Mail: chenyz@corp.netease.com
分享到:
评论

相关推荐

    易语言 xml解析 易语言 xml解析 教程 带源码

    6. **错误处理**:在解析过程中,可能会遇到语法错误、文件读取错误等问题,因此,编写程序时需要包含适当的错误处理机制,如异常捕获和处理,以确保程序的健壮性。 7. **实际应用**:了解了基本的XML解析方法后,...

    PB 解析xml格式串

    2. **XML解析**:XML文档由元素、属性、文本等构成,解析XML时,我们需要读取这些元素并将其转换为内存中的数据结构。Python中可以使用`xml.etree.ElementTree`库进行解析,Java中可使用DOM或SAX解析器。 3. **XML...

    Sax解析XML文件解析

    **SAX解析XML的基本原理:** SAX解析器以流式的方式读取XML文档,当遇到文档的各个元素时,会触发相应的事件,如开始文档、开始元素、结束元素、字符数据等。程序员通过实现SAX解析器的回调接口来处理这些事件,从而...

    关于解析xml的一些demo

    在本文中,我们将深入探讨XML的基本概念、解析XML的方法以及如何使用示例代码进行操作。 XML的设计目标是传输和存储数据,而不是显示数据,这与HTML的主要区别在于HTML主要用于网页展示。XML文档由元素、属性、文本...

    DOM4J解析XML时DTD路径问题

    ### DOM4J解析XML时DTD路径问题 在处理XML文件时,经常需要用到DOM4J这样的库来进行解析。当XML文件包含DTD(Document Type Definition)声明时,DOM4J默认会尝试从指定的URL加载DTD文件来进行验证。这通常是为了...

    xml 解析 xml 解析几何

    解析XML主要有两种方法:DOM(Document Object Model)和SAX(Simple API for XML)。 1. DOM解析: DOM解析器将整个XML文档加载到内存中,创建一个树形结构,允许开发者通过节点遍历和操作XML数据。例如,`...

    解析XML特殊字符方法

    有两种主要方法来解析XML中的特殊字符: **方法一:使用实体引用** 实体引用是XML中最常见的处理特殊字符的方式。当你需要在XML文档中插入特殊字符时,可以使用对应的实体引用。比如,如果你想在文本中包含一个...

    xml.rar_XML c语言_c语言 xml_resolver_xml解析 c_解析xml

    开发者可以通过这个文件测试解析器是否能正确解析XML文档的元素、属性、文本内容以及处理命名空间、实体引用等特性。 解析XML的过程中,需要注意以下几个关键点: 1. **语法验证**:确保XML文档符合W3C标准,包括...

    android下解析xml文件的demo

    SAX解析器是事件驱动的,它逐行读取XML文件,遇到每个元素时触发相应的事件。这种方式适用于处理大型XML文件,因为它不需要一次性加载整个文件。 在"ReadXMLDemo"中,使用SAX解析的步骤如下: - 实现`...

    xml解析文件的两种方式

    总结,选择DOM还是SAX解析XML取决于具体需求,包括文件大小、处理速度、内存限制以及是否需要随机访问数据。在实际开发中,根据项目特点灵活选择合适的解析方式,能有效提高程序性能和资源利用效率。

    weblogic无法解析xml解决办法

    有些情况下,在开发web项目中会遇到weblogic无法解析xml的错误,是因为weblogic在解析xml时是调用自己的方法去解析,会产生一些莫名其妙的错误,我们只要在web-inf下添加weblogic.xml让其让出解析权即可.

    C++完整解析XML

    - 安全性:防止XXE(XML External Entity)攻击,避免在解析XML时加载不受信任的外部实体。 6. **实战应用** - 配置文件:XML常用于存储程序配置,C++可以方便地解析和写入这些配置。 - 数据交换:在不同系统间...

    Sax解析xml文件

    SAX解析器的工作原理是基于事件驱动的,它在解析XML文档时会触发一系列的事件,如开始文档、结束文档、开始元素、结束元素等。开发者通过实现SAX解析器的回调接口(如ContentHandler),在这些事件发生时执行相应的...

    XmlPullParser解析Xml文件解析demo

    XmlPullParser是Android系统提供的一种解析XML文件的API,它是一种基于事件驱动的解析方式,能够高效、节省资源地处理XML文档。在这个“XmlPullParser解析Xml文件解析demo”中,我们将探讨如何利用XmlPullParser来...

    解析XML时用到的架包

    根据提供的标题和描述,我们可以推测这个压缩包包含了一些用于解析XML的Java库。虽然具体是哪五个库没有明确列出,但这里我会介绍一些常见的用于解析XML的Java框架,以及它们各自的特点和应用场景。 1. **DOM...

    android 解析XML文件 生成XML文件

    SAX(Simple API for XML)是一种事件驱动的解析器,它不会一次性加载整个XML文档到内存,而是逐行读取,遇到元素、属性等时触发相应的事件。这种解析方式适用于处理大型XML文件,节省内存资源。以下是在Java和...

    C++解析xml源码

    对于C++开发者来说,理解如何解析XML源码是提高软件开发能力的重要环节。本篇文章将详细介绍使用C++进行XML解析的相关知识点。 首先,XML文档的结构基于元素(Elements)、属性(Attributes)以及内容(Content)。...

    Pull解析xml源码导入即可用

    本文将深入探讨Android中的Pull解析XML技术,以及如何利用模板快速实现XML的解析。 首先,理解XML Pull解析器的工作原理是至关重要的。在Android中,XML Pull解析是一种轻量级处理XML文档的方式,它允许应用移动...

    Java SAX解析Xml文档Demo

    本示例将详细解释如何在Java中使用SAX解析XML文档,并通过注释进行详细说明。 首先,我们需要引入SAX解析器的依赖库,通常这可以通过在项目构建配置中添加JAXB或Xerces实现来实现。 ```java // 引入必要的库,如...

    C++ XML文件解析库 tinyxml2

    4. **错误处理**:TinyXML2提供了一个简单的错误处理机制,当解析或操作XML时遇到问题,会返回一个错误代码,通过`ErrorId()`和`ErrorStr()`可以获取详细的错误信息。 5. **内存管理**:TinyXML2使用智能指针来管理...

Global site tag (gtag.js) - Google Analytics