如何在Java中简洁地构建XML文档?

21
我需要从Java对象层次结构构建一个XML文档。Java类和XML格式都是固定的,因此我不能使用像XStream这样的XML序列化程序:它基于Java类来生成XML格式。同样,像JAXB这样的Java XML绑定技术也行不通,因为它会从XML模式创建Java类[注:但见下文]。我需要手动处理。
低技术的StringBuilder方法会导致脆弱和有缺陷的代码(至少对我来说如此!)。
JAXPJDOM这样的API会产生更健壮的代码,但这些代码相当冗长。 Groovy具有优雅的MarkupBuilder
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.records() {
  car(name:'HSV Maloo', make:'Holden', year:2006) {
    country('Australia')
    record(type:'speed', 'Production Pickup Truck with speed of 271kph')
  }
  car(name:'P50', make:'Peel', year:1962) {
    country('Isle of Man')
    record(type:'size', 'Smallest Street-Legal Car at 99cm wide and 59 kg')
  }
}

其他编程语言(例如Ruby)有更好的XML构建工具,但我想保持使用纯Java。目前似乎有一些新的Java XML构建工具,例如practicalxml和James Murty的xmlbuilder

在Java中构建XML文档的更优雅的方法是什么?

总结:

Jon Doe建议使用dom4jjdom

CurtainDog建议无论如何都要使用JAXB,并指出jherico的建议很重要:然后可以使用Dozer在当前的JavaBeans和JAXB JavaBeans之间进行映射。

thaggie推荐使用JIBX,并与CurtainDog和jherico一致认为绑定技术实际上是可行的。

StaxMan推荐使用StaxMate

我看过的东西中,practicalxml和James Murty的xmlbuilder似乎是最简洁的构建器,但它们比较新。像JAXB这样的绑定技术似乎提供了额外的安全性/自动化。在主流选择中,dom4j似乎还不错,但仍然有点啰嗦。它提供了“流畅接口”(变异体返回对已变异对象的引用,因此它们可以链接在一起),我很喜欢:

public Document createDocument() {
    Document document = DocumentHelper.createDocument();
    Element root = document.addElement( "root" );
    Element author2 = root.addElement( "author" )
      .addAttribute( "name", "Toby" )
      .addAttribute( "location", "Germany" )
      .addText( "Tobias Rademacher" );
    Element author1 = root.addElement( "author" )
      .addAttribute( "name", "James" )
      .addAttribute( "location", "UK" )
      .addText( "James Strachan" );
    return document;
}

为了简洁起见,您可以在此API上包装一个薄外观,以提供一些方法的简略同义词(例如,attr()代替addAttribute())。

谢谢大家!

P.S.:Stephan Schmidt曾经开发过一个Java MarkupBuilder,但似乎没有发布。


请修复dom4j链接到http://dom4j.sourceforge.net/ :) - Pawel Veselov
@PawelVeselov -- 谢谢,dom4j.org被占用的情况很令人悲哀。 - Jim Ferrans
(O/T)@JimFerrans 我认为它没有被收编,他们只是不再提及dom4j软件了。他们的页面样式与dom4j库页面之间的相似之处太多了,这些人不可能没有同一个屋檐下 :) - Pawel Veselov
@PawelVeselov -- 哦,但是看一下底部的链接(http://www.yxymedia.com/):这是一家搜索引擎优化(SEO)公司。当dom4j.org域名可用时,他们接管了它,并编写了类似的页面,可能是为了将流量引导到他们的商业网站。我认为他们甚至没有链接到sourceforge.net网站。 - Jim Ferrans
(O/T) 唉,现在的人... - Pawel Veselov
6个回答

11

dom4j或jdom可能是最优雅的,您可以按照自己喜欢的方式编写代码。如果我没记错的话,Dom4j有构建器,并且代码更冗长。

Element.addElement("x").setAttribute("x", "y").xxxxx;

谢谢,我没有考虑过dom4j。 - Jim Ferrans

2

请看XOM。它快速、简洁、正确,而且不啰嗦。


1

Underscore-java有一个构建器,可以从对象创建XML字符串。

    String xml = U.objectBuilder().add("author", U.arrayBuilder()
            .add(U.objectBuilder()
                .add("-name", "Toby")
                .add("-location", "Germany")
                .add("#text", "Tobias Rademacher"))
            .add(U.objectBuilder()
                .add("-name", "James")
                .add("-location", "UK")
                .add("#text", "James Strachan"))).toXml();

// <?xml version="1.0" encoding="UTF-8"?>
// <root>
//   <author name="Toby" location="Germany">Tobias Rademacher</author>
//   <author name="James" location="UK">James Strachan</author>
// </root>

1

为什么不直接使用JAXB呢?这样问题就变成了一个非常简单的对象到对象映射,而你也可以完全避免处理XML。


我需要编写一个对象到 XML 的映射,其中 XML 是一个固定的标准(CableLabs' ADI 1.1),而 Java 类也是预先确定的。 - Jim Ferrans
使用JAXB将Java类映射到Schema,然后使用Dozer从JAXB类映射到预定的Java类。 - Jherico
@Jherico:谢谢,我还没有看过Dozer。所以你可以使用JAXB从所需模式创建相应的JavaBean类集,然后设置一个Dozer映射,将现有的JavaBeans映射到JAXB JavaBeans。听起来需要更多的代码,但也更自动化。我现在明白CurtainDog的意思了。 - Jim Ferrans

1

虽然不如脚本语言中的构建器那么简洁,StaxMate 使事情变得非常简单;通常与树模型在结构上一样简单,但它还支持类型添加(隐式转换)。并且所有这些都直接进入流中,意味着非常低的内存使用量(如果有必要,则速度很快)。

值得一提的是,它也支持流畅的风格(自2.0.x起),因为它经常是有意义的。与完整数据绑定(和树模型)解决方案相比,其主要优点可能是低内存使用率;几乎没有状态保留下来,所有输出尽可能快地发送到目标。


0

你可以考虑使用JIBX,你可以定义一个mapping,将你的领域模型类映射到目标XML模式。

或者,如果不可能的话,虽然我知道你已经排除了使用绑定技术,但我鼓励你重新审视这个决定。从你的领域模型复制到生成的模型中,很可能会产生更清晰、更易于维护和更少出错的代码,这也是JIBX可以做到的。

我应该补充一下,在我的经验中,在这里问关于JIBX的问题是无用的,但他们的邮件列表非常有帮助。


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