有没有更简单的方法在 Java 中解析 XML?

Posted

技术标签:

【中文标题】有没有更简单的方法在 Java 中解析 XML?【英文标题】:Is there an easier way to parse XML in Java? 【发布时间】:2010-12-15 17:03:59 【问题描述】:

我正试图弄清楚如何解析一些 XML(对于 android 应用程序),而用 Java 来做这件事似乎很荒谬。似乎它需要创建一个具有各种回调(startElement、endElement 等)的 XML 处理程序,然后您必须注意将所有这些数据更改为对象。类似this tutorial。

我真正需要的只是将一个 XML 文档更改为一个多维数组,更好的是拥有某种Hpricot 处理器。有没有办法做到这一点,还是我真的必须在上面的示例中编写所有额外的代码?

【问题讨论】:

如果你只对解析(小)XML配置文件感兴趣,我建议你看看XPath。我通常使用它,因为它可以很容易地访问。但是,如果您使用大型 XML 文件,性能会变得更差。 【参考方案1】:

Java 中有两种不同类型的 XML 处理器(实际上是 3 种,但一种很奇怪)。您拥有的是 SAX 解析器,而您想要的是 DOM 解析器。查看http://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/ 了解如何使用 DOM 解析器。 DOM 将创建一棵树,您可以轻松浏览它。 SAX 最适合大型文档,但如果速度较慢且内存占用更多​​,则 DOM 会更容易。

【讨论】:

第三个是什么?我只熟悉 SAX 和 DOM。 拉解析器有什么奇怪的地方? StAX 在 Android 上甚至不可用?你在说什么 太棒了,那个链接正是我要找的。​​span> 基准开源,10分钟内下载自己试用【参考方案2】:

试试http://simple.sourceforge.net,它是一个XML到Java的序列化和绑定框架,它完全兼容Android并且非常轻量级,270K并且没有依赖。

【讨论】:

这应该会得到更多人的支持,这确实是在 Android 上使用 XML 的最佳方式。用它。如果您不知道如何将其包含在 Android 项目中,请查看这篇博文:massaioli.homelinux.com/wordpress/2011/04/21/… 这几乎就是 Java 中 Gson 对 Json 的意义! :D 很棒的图书馆! 你确定它没有依赖关系吗?当我从 maven 添加 simple 时,xpp、stax 和 stax-api 出现在 i.imgur.com/T3h7Pb1.png【参考方案3】:

凯尔,

(请原谅这篇文章的自我推销性质......我已经在这个库上工作了几个月,它都是开源/Apache 2,所以不是自私自利,只是想提供帮助)。

我刚刚发布了一个库,我称之为 SJXP 或“Simple Java XML Parser” http://www.thebuzzmedia.com/software/simple-java-xml-parser-sjxp/

它是一个非常小/紧凑(4 类)的抽象层,位于任何符合规范的 XML Pull Parser 之上。

在 Android 和非 Android Java 平台上,拉式解析可能是性能最高(速度和内存开销低)的解析方法之一。不幸的是,直接针对拉式解析器进行编码最终看起来很像任何其他 XML 解析代码(例如 SAX)——您有异常处理程序、维护解析器状态、错误检查、事件处理、值解析等。

SJXP 的作用是允许您在文档中定义您想要从中获取值的元素或属性的类似 XPath 的“路径”,例如:

/rss/频道/标题

当该规则匹配时,它将调用您的回调,并带有该值。该 API 非常直接,并且对命名空间限定的元素具有直观的支持,如果这是您尝试解析的内容。

标准解析器的代码如下所示(解析 RSS2 提要标题的示例):

IRule titleRule = new DefaultRule(Type.CHARACTER, "/rss/channel/title") 
@Override
public void handleParsedCharacters(XMLParser parser, String text) 
    // Store the title in a DB or something fancy

然后您只需创建一个 XMLParser 实例并为其提供您希望它关心的所有规则:

XMLParser parser = new XMLParser(titleRule);
parser.parse(xmlStream);

就是这样,每次规则匹配时解析器都会调用处理程序方法。如果需要,您可以随时调用 parser.stop() 停止解析。

此外(这是这个库的真正优势)匹配命名空间限定的元素和属性非常容易,您只需将它们的命名空间 URI 添加到路径中元素名称前缀的括号内。

举个例子,假设你想要一个 RSS 提要的元素,这样你就可以知道它是什么语言(参考:http://web.resource.org/rss/1.0/modules/dc/)。您只需为带有“dc”前缀的“语言”元素使用唯一的命名空间 URI,规则路径最终看起来像这样:

/rss/channel/[http://purl.org/dc/elements/1.1/]语言

命名空间限定的属性也是如此。

如此简单,您添加到解析过程中的唯一开销是在 XML 文档的每个位置进行 O(1) 哈希查找,以及解析器内部位置状态的几百字节,可能是 1k .

该库可以在没有额外依赖项的 Android 上运行(因为该平台已经提供了 org.xmlpull impl),并且通过添加 XPP3 依赖项可以在任何其他 Java 运行时中运行。

这个库是几个月来为每种语言的每种提要 XML 编写自定义拉式解析器的结果,并且意识到(随着时间的推移)大约 90% 的解析可以提炼成这个真正基本的范例。

我希望你觉得它很方便。

【讨论】:

【参考方案4】:

从 Java 5 开始,SDK 中有一个 XPath 库。有关它的介绍,请参阅this tutorial。

【讨论】:

【参考方案5】:

在我看来,您应该使用 SAX 解析器,因为: - 快速地 - 您可以控制 XML 文档中的所有内容

您将花费更多时间进行编码,但这是一次,因为您将创建代码模板来解析 XML

从第二种情况开始,您只需编辑更改的内容。

祝你好运!

【讨论】:

【参考方案6】:

我创建了一个非常简单的 API 来准确解决这个问题。它只是一个可以包含在代码库中的类,它非常干净且易于解析任何 XML。你可以在这里找到它:

http://argonrain.wordpress.com/2009/10/27/000/

【讨论】:

【参考方案7】:

你可以试试这个http://xml.jcabi.com/ 它是 DOM 之上的一个额外层,允许对 XML 文档和节点进行简单的解析、打印和转换

【讨论】:

小心点。它有很多依赖项,我的 Spring Boot 应用程序无法启动,因为它在类路径中检测到某些东西(这个库是唯一的添加)【参考方案8】:

在我看来,使用XPath for parsing XML 可能是您最简单的编码方法。您可以在单个表达式中体现从 XML 文档中提取节点的逻辑,而不必编写代码来遍历文档的对象图。

我注意到another posted answer to this question 已经建议使用 XPath。 但您的 Android 项目还没有。截至目前,任何 Android 版本尚不支持 XPath 解析类(即使 javax.xml 命名空间是在 Dalvik JVM 中定义的,这可能会欺骗你,就像我一开始那样)。

在 Android 中包含 XPath 类是当前处于后期阶段的工作项目。 (在我撰写本文时,Google 正在对其进行测试和调试)。您可以在此处跟踪将 XPath 添加到 Davlik 的状态:http://code.google.com/p/android/issues/detail?id=515

(令人烦恼的是,您不能假设大多数 Java VM 支持的东西都包含在 Android Dalvik VM 中。)

在等待 Google 官方支持时,另一个选项是 JDOM,它目前声称与 Dalvik VM 兼容并且还支持 XPath(测试版)。 (我没有检查过这个;我只是重复他们网站上的当前声明。)

【讨论】:

【参考方案9】:

您还可以使用Castor 将 XML 映射到 Java bean。我以前用过它,它就像一个魅力。

【讨论】:

在网站上找不到此链接。你能帮帮我吗?【参考方案10】:

SAX handler 是最好的方法。一旦你这样做了,你将永远不会回到其他任何事情上。它快速、简单,并且随着它的运行而嘎吱作响,不会将大部分内容吸入内存中,也不会将整个 DOM 放入内存中。

【讨论】:

【参考方案11】:

几周前,我开发了一个小型库(javax.xml.stream.XMLEventReader 的包装器),它允许以类似于手写递归下降解析器的方式解析 XML。来源是available on github,下面是一个简单的使用示例。不幸的是,Android 不支持此 API,但它与支持的 XmlPullParser API 非常相似,并且移植不会太耗时。

accept("tilesets");
    while (atTag("tileset")) 
        String filename = attrib("file");
        File tilesetFile = new File(filename);
        if (!tilesetFile.isAbsolute()) 
            tilesetFile = new File(FilenameUtils.concat(file.getParent(), filename));
        
        int tilesize = Integer.valueOf(attrib("tilesize"));
        Tileset t = new Tileset(tilesetFile, tilesize);
        t.setID(attrib("id"));
        tilesets.add(t);

        accept();
        close();
    
close();

expect("map");

int width       = Integer.valueOf(attrib("width"));
int height      = Integer.valueOf(attrib("height"));
int tilesize    = Integer.valueOf(attrib("tilesize"));

【讨论】:

【参考方案12】:

对于任何类型的 xml,有一个非常好的示例展示了 XmlPullParser。它也可以解析为通用方式,您无需更改任何内容,只需获取该类并将其放入您的 android 项目中。

Generic XmlPullParser

【讨论】:

【参考方案13】:

解析 XML 不是一件容易的事。

它的基本结构是一棵树,树中的任何节点都可以容纳一个容器,该容器由多个树的数组组成。

树中的每个节点都包含一个标签和一个值,但另外还可以包含任意数量的命名属性,以及任意数量的子节点或容器。

XML 解析任务往往分为三类。

可以用“正则表达式”完成的事情。例如。您想查找第一个“MailTo”标签的值,并且对任何其他标签的内容不感兴趣。

你可以自己解析的东西。 xml 结构总是非常简单,例如一个根节点和十个具有简单值的知名标签。

剩下的!尽管 xml 消息格式看起来很简单,但自制的解析器很容易被额外的属性、CDATA 和意想不到的孩子弄糊涂。成熟的 XML 解析器可以处理所有这些情况。这里的基本选择是在流或 DOM 解析器之间。如果您打算使用按您想要使用它们的顺序给出的大多数实体/属性,那么 DOM 解析器是理想的。如果您只对几个属性感兴趣并打算按照它们出现的顺序使用它们,如果您有性能限制,或者,如果 xml 文件很大(> 500MB),那么流解析器是最好的选择;回调机制需要一些“摸索”,但一旦掌握了它,它的编程实际上非常简单。

【讨论】:

您是否认真建议应该对“简单”案例使用正则表达式或自制的 XML 解析器? -1 除非性能是重要因素,否则不会真正推荐它。例如,如果您基于客户编号进行负载平衡,那么仅扫描第一个 CustNo 标记而不是启动完整的怪物 XML 解析器可能是有意义的。 James,使用正则表达式引擎将字符串与表达式进行匹配比基于词法分析的方法(如 XML 解析)要昂贵得多;尤其是使用快速提取解析器或 SAX 解析器。我不是为了“冷落”你而发布这个消息,只是让你知道,如果你真的将正则表达式方法推广到一个大规模的可扩展应用程序,你可能想要改变它。 就像我说的,我不会真的推荐这种方法。也许我应该在帖子中更多地强调缺点!

以上是关于有没有更简单的方法在 Java 中解析 XML?的主要内容,如果未能解决你的问题,请参考以下文章

在将 XML 文件解组为对象后,如何让 JAXB 调用方法?

解析 XML 的更简单方法

在 Java 中解析字节数组

在java中解析xml

java操作xml超简单的方法

domSAXJdomdom4j四种解析xml方式简单总结