创建XML文件的最快和最有效的方法是什么?

9
什么是在Java中创建XML文档最快、最有效的方法?有很多库可供选择(如woodstox、xom、xstream…),不知道哪个更好。我应该采用代码生成方法(因为XML模式已经知道了)还是运行时反射方法?
附加信息:
1. 已有明确定义的XML Schema,并且很少更改。
2. 要求将Java对象转换为XML,而不是相反。
3. 每秒需要将数千个Java对象转换为XML。
4. 代码生成、代码复杂度、配置、维护等方面次于高性能。

2
你如何定义高效?最少的内存使用?最少的代码行数?做什么最快?编排?对大型文档进行反编排?美化输出?你正在做什么需要“最快”的库?一定要根据真正重要的标准选择库,而不是无关紧要的标准。你可能会发现,选择一个“足够快”的库更好,因为它比选择“最快”的库更容易使用,而且维护起来也不会给你带来头疼。 - Paul
1
“Most efficient”这个短语不是很清晰。最高效用于内存还是CPU?需要进一步澄清。 - Erdinç Taşkın
1
可能是Which xml serialization library is performance oriented?的重复问题。 - skaffman
保罗:我的要求是尽可能快速,尽量少花时间。编码或配置的数量,维护都不重要。XML Schema也可用。高效意味着合理的内存使用,无故障运行,没有内存泄漏,因为它每秒处理数千条记录,在业界广为人知等等。希望这样能澄清问题。 - arrehman
6个回答

15
如果我要创建一个非常简单的 XML 内容,我会仅使用 JDK api,不引入第三方依赖。
因此,对于简单的 XML,如果我要将 XML 文件映射到 Java 类(或反之),我会选择 JAXB。请参见 本教程,了解它有多么容易。
现在。
如果我要创建一些更复杂的 XML 输出,并保持其常量结构,我会使用一些模板引擎,比如 FreemarkerThymeleaf 也很不错。
最后。
如果我要非常有效地创建大型 XML 文件,我会使用 SAX 解析器
我希望你现在明白了,你有很多选择 - 选择最适合你需求的即可 :)
祝玩得愉快!

6
我不认为StringBuilder是创建有效xml的简单方法。我认为这是最复杂的方式,因为你必须自己完成所有工作。例如,看看使用EclipseLink MOXy从对象创建xml有多么容易:MOXy: 入门 这比使用StringBuilder要容易得多。 - Paul
1
谢谢Lukas,如前面的评论所提到的,我想要更快的性能。XML并不是很大。我不需要将XML文件映射到Java对象。因此,这有助于缩小范围。我喜欢模板引擎的想法,我会研究一下。我会在这里发布我的经验。 - arrehman
1
@Paul引用的例子可以与任何JAXB实现一起使用,Java SE 6开始的JDK / JRE中已包含其中一个。 - bdoughan
+1 包括模板替代方案,这经常被忽略了。 - Christophe Roussy
你提到使用SAX解析器来编写大型XML文件。你打算如何做到呢?SAX解析器没有任何输出方法。适用于读取大文件,但不适用于编写。你可能在考虑使用SAX框架,例如https://dev59.com/OG445IYBdhLWcg3wXZIy,但是你应该更正你的答案以解决这个问题。 - Anthill
显示剩余2条评论

6
尝试使用Xembly,这是一个小型的开源库,可以使XML创建过程变得非常简单和直观。
String xml = new Xembler(
  new Directives()
    .add("root")
    .add("order")
    .attr("id", "553")
    .set("$140.00")
).xml();

Xembly是原生Java DOM的一个包装器,是一个非常轻量级的库(我是一名开发人员)。


1
我也觉得这篇文章很有帮助:http://www.yegor256.com/2014/04/09/xembly-intro.html - Bernie Noel
1
你的库看起来很有用,但它是否高效呢?当适当时消除冗长确实不错,但问题是编写 XML 的最快和最有效的方法。从上面的示例来看,我会说它不是一个好的解决方案来高效地编写大型 XML 文件。尽管我喜欢你的库用于其他用例,但我觉得把它作为最快和最有效的建议并不准确,而是在推广你的产品而不是提供最佳答案。如果我错了,请纠正我。 - user1441149

2
我知道的最好的方法是使用一个能够创建节点的XPath引擎。XMLBeam可以做到这一点(在这里的JUnit测试中):XMLBeam
    public interface Projection {

    @XBWrite("/create/some/xml/structure[@even='with Predicates']")
    void demo(String value);
}

@Test
public void demo() {
    Projection projection = new XBProjector(Flags.TO_STRING_RENDERS_XML).projectEmptyDocument(Projection.class);
    projection.demo("Some value");
    System.out.println(projection);
 }

这个程序会打印出:
<create>
   <some>
      <xml>
        <structure even="with Predicates">Some value</structure>
      </xml>
   </some>
</create>

2
首先,正确的序列化非常重要。手写序列化器通常不太准确。例如,它们往往会忘记文本节点中不能出现字符串“]]>”。
如果您是一位有能力的Java程序员,编写既正确又快速的自己的序列化器并不太困难,但由于之前已经有一些非常有能力的Java程序员写过类似的代码,因此您可能无法在性能上超越他们,也不值得花费精力编写自己的代码。
除了个别情况下,大多数通用库可能会因提供序列化选项(如缩进、编码或选择行结束符)而稍微变慢。通过避免不必要的功能,您可能只能挤出一点额外的性能。
此外,一些通用库可能会检查您提交给它们的内容的格式是否正确,例如检查命名空间前缀是否已声明(或者在未声明时进行声明)。如果它不执行任何检查,您可能会使其更快。另一方面,您可能会创建一个快速但难以使用的库。将性能置于其他所有目标之上几乎总是错误的。
至于可用库的性能,请对它们进行测量,并告诉我们您的发现。

您提到了关于性能的一些重要方面。谢谢。 - arrehman

2

使用XMLStreamWriter。

我运行了一个微基准测试,序列化了一百万个这样的对象:

@XmlRootElement(name = "Root")
public class Root {
    @XmlAttribute
    public String attr;
    @XmlElement(name = "F1")
    public String f1;
    @XmlElement(name = "F2")
    public String f2;
}

带着这些结果:

JAXB: 3464 millis (<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Root attr="at999999"><F1>x999999</F1><F2>y999999</F2></Root>)
XMLStreamWriter: 1604 millis (<?xml version="1.0" ?><Root attr="at999999"><F1>x999999</F1><F2>y999999</F2></Root>)
Xembly: 25832 millis (<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Root attr="at999999">
<F1>x999999</F1>
<F2>y999999</F2>
</Root>
)
StringBuilder: 60 millis (<?xml version="1.0" encoding="UTF-8"><Root attr=")at999999"><F1>x999999</F1><F2>y999999</F2></Root>)
StringBuilder w/escaping: 3806 millis (<?xml version="1.0" encoding="UTF-8"><Root attr="at999999"><F1>x999999</F1><F2>y999999</F2></Root>)

这段代码的输出结果为:
  • StringBuilder: 60 毫秒
  • XMLStreamWriter: 1604 毫秒
  • JAXB: 3464 毫秒
  • 使用非常原始的转义的 StringBuilder: 3806 毫秒
  • Xembly: 25832 毫秒
  • 还有很多我没有尝试过的
其中,StringBuilder 是最高效的,因为它不需要在所有文本中搜索 ", &, <, 和 > 并将它们转换为 XML 实体。

1
嗨Petr,老实说,这是最相关的答案。但是XMLStreamWriter是哪个?我看到JDK 8仅将其包含为具有一些“com.sun.”实现的接口。还有Apache Commons似乎也有一个。你在这个基准测试中使用了哪个?谢谢 - 62mkv

1

受Petr答案的启发,我花了一整天时间实现了这样一个基准测试,并在此过程中阅读了大量关于JMH的文章。 项目在这里:https://github.com/62mkv/xml-serialization-benchmark

结果如下:

Benchmark                                          (N)   Mode  Cnt    Score    Error  Units
XmlSerializationBenchmark.testWithJaxb              50  thrpt    5  216,758 ± 99,951  ops/s
XmlSerializationBenchmark.testWithXStream           50  thrpt    5   40,177 ±  1,768  ops/s
XmlSerializationBenchmark.testWithXmlStreamWriter   50  thrpt    5  520,360 ± 14,745  ops/s

我没有包含Xembly,因为根据它的描述,它似乎对于这种特定情况来说有些过度。

我有点惊讶于XStream的表现如此糟糕,因为它来自ThoughtWorks,但可能只是因为我没有为这个特定情况定制得足够好。而默认的Java 8标准库StAX实现对于性能来说是最好的。但在开发体验方面,XStream是使用最简单的,而XMLStreamWriter也需要更多容易出错的努力来完全实现;而JAXB在两个提名中都名列第二。

PS:非常欢迎反馈和建议以改进套件!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接