从.XSD文件生成Java类吗?


127

我有一个巨大的QuickBooks SDK .XSD模式文件,该文件定义了我可以从QuickBooks发送/接收的XML请求/响应。

我希望能够轻松地从这些.XSD文件生成Java类,然后将其用于将XML编组为Java对象,然后将Java对象编组为XML。

是否有捷径可寻...?

理想情况下,它在运行时不需要基本Java发行版外部的任何库。但是我很灵活


6
如果要手动生成,请将.xsd文件放在eclipse项目中,右键单击该文件,然后单击“生成”
Junchen Liu

Answers:


121

JAXB确实可以满足您的需求。从1.6开始,它内置在JRE / JDK中


7
不幸的是,此功能自Java 9起将不再可用。这是因为所涉及的类(尤其是com.sun.tools.xjc。*类)将不再通过JDK提供。
马可(Marco)2016年

4
我认为从JDK中删除此问题不应该成为问题,因为java.net项目(答案中链接)可能会保留下来。
stmoebius 16/09/14

1
如此处所述,您可以通过命令行参数在Java 9中添加依赖项,也可以手动添加依赖项。
马提亚斯·荣格

118

为了扩展上面的“ use JAXB”注释,

在Windows中 "%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd

例如, "%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

稍等一下,如果您拥有格式正确的XSD文件,则将获得一些格式良好的Java类。


3
十分感谢!要生成顶级类而不是封装类,请参见:stackoverflow.com/questions/13175224/…。如果它导致类名冲突,请参见:stackoverflow.com/questions/13414407/…–
明天

38

如果要在不到5分钟的时间内开始将Java编码为XML和将XML编码为Java,请尝试“简单XML序列化”。不要花数小时学习JAXB API http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

但是,如果您真的很想学习JAXB,那么这里的教程很好 http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml

教程内容:

JAXB,用于简单的Java-XML序列化

在Java中有多种方法可以进行XML序列化。如果您希望对解析和序列化进行细粒度的控制,则可以使用SAX,DOM或Stax以获得更好的性能。但是,我经常想做的是在POJO和XML之间进行简单的映射。但是,创建Java类来手动进行XML事件解析并非易事。最近,我发现JAXB是一种快速便捷的Java-XML映射或序列化。

JAXB包含许多有用的功能,您可以在此处查看参考实现。Kohsuke的Blog也是了解JAXB的好资源。对于此博客文章,我将向您展示如何使用JAXB进行简单的Java-XML序列化。

POJO到XML

假设我有一个Item Java对象。我想将Item对象序列化为XML格式。我首先要做的是用来自javax.xml.bind.annotation。*包的一些XML注释对POJO进行注释。请参阅代码清单1中的Item.java

从代码

  • @XmlRootElement(name="Item") 表示我想成为根元素。
  • @XmlType(propOrder = {"name", "price"}) 指示我希望元素在XML输出中排列的顺序。
  • @XmlAttribute(name="id", ...) 表示id是根元素的属性。
  • @XmlElement(....) 表示我希望价格和名称成为Item中的元素。

Item.java准备好了 然后,我可以继续创建用于封送Item的JAXB脚本。

//creating Item data object
Item item = new Item();
item.setId(2);
item.setName("Foo");
item.setPrice(200);
.....

JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
//I want to save the output file to item.xml
marshaller.marshal(item, new FileWriter("item.xml"));

有关完整的代码清单,请参见代码清单2 main.java。输出代码清单3 item.xml文件已创建。看起来像这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.sun.com/teera/ns/item">

 <ns1:itemName>Foo</ns1:itemName>
<ns1:price>200</ns1:price>

</ns1:item>

容易吧?您也可以通过简单地更改marshal(...)方法的参数,将输出XML转换为文本String,Stream,Writer,ContentHandler等。

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
// save xml output to the OutputStream instance
marshaller.marshal(item, <java.io.OutputStream instance>);

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
//save to StringWriter, you can then call sw.toString() to get java.lang.String
marshaller.marshal(item, sw);

XML到POJO

让我们逆转这一过程。假设我现在有一段XML字符串数据,并且想要将其变成Item.java对象。XML数据(代码清单3)如下所示

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.sun.com/teera/ns/item">
<ns1:itemName>Bar</ns1:itemName>
<ns1:price>80</ns1:price>
</ns1:item>

然后,我可以通过以下方式将该XML代码编组到Item对象:

...
ByteArrayInputStream xmlContentBytes = new ByteArrayInputStream (xmlContent.getBytes());
JAXBContext context = JAXBContext.newInstance(Item.getClass());
Unmarshaller unmarshaller = context.createUnmarshaller();
//note: setting schema to null will turn validator off
unmarshaller.setSchema(null);
Object xmlObject = Item.getClass().cast(unmarshaller.unmarshal(xmlContentBytes));
return xmlObject;
...

有关完整的代码清单,请参见代码清单2(main.java)。XML源可以来自Stream和file两种形式。同样,唯一的区别是方法参数:

...
unmarshaller.unmarshal(new File("Item.xml")); // reading from file
...
// inputStream is an instance of java.io.InputStream, reading from stream
unmarshaller.unmarshal(inputStream);

使用XML模式进行验证

我在这里要提到的最后一件事是在解组到Java对象之前使用架构验证输入XML。我创建一个名为item.xsd的XML模式文件。有关完整的代码清单,请参见代码清单4(Item.xsd)。现在,我要做的就是注册此架构以进行验证。

...
Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File("Item.xsd"));
unmarshaller.setSchema(schema); //register item.xsd shcema for validation
...

当我尝试将XML数据解组到POJO时,如果输入的XML不符合架构,则会捕获异常。有关完整的代码清单,请参见代码清单5(invalid_item.xml)。

javax.xml.bind.UnmarshalException
- with linked exception:
javax.xml.bind.JAXBException caught: null
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'item1' is
                                not a valid value for 'integer'.]

在这里,我将'id'属性更改为字符串而不是整数。

如果XML输入针对该模式有效,则XML数据将成功解组到Item.java对象。


1
对于我需要的功能,这看起来非常有前途,并且比JAXB之类的大而复杂的方法简单得多。不幸的是,我看不到将现有的.XSD转换为.class文件的任何方法,这确实是我需要开始的。有没有办法做到这一点?
基思·帕尔默(Keith Palmer)2009年

7
不幸的是,带有JAXB教程的博客处于离线状态。
Luis C.

我们可以使用jaxb2-maven-plugin轻松完成此操作,请查看本教程journaldev.com/1312/…–
Pankaj

“”%java_home%\ bin \ xjc“ -p [您的命名空间] [xsd_file] .xsd有什么复杂的?
gorefest


17

最简单的方法是使用命令行。只需输入.xsd文件的目录:

xjc myFile.xsd.

因此,java将生成所有Pojos。


14

Maven可以用于此目的,您需要添加一些依赖项并清理您的应用程序。您将在目标文件夹中自动创建所有类。

只需将它们从目标复制到所需位置,这是我用来从xsd文件创建分类的pom.xml:

    <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>jaxb2-maven-plugin</artifactId>

     <executions>
      <execution>
       <goals>
        <goal>xjc</goal>
       </goals>
      </execution>
     </executions>
     <configuration>
      <schemaDirectory>src/main/webapp/schemas/</schemaDirectory>
     </configuration>
    </plugin>

   </plugins>
  </pluginManagement>
 </build>
</project>

只需将您的xsd文件放在“ src / main / webapp / schemas /”下,maven就会在编译时找到它们。

希望这会对您有所帮助,有关更多信息,请访问http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

希望它会有所帮助:)


1
这实际上与资源目录一起使用吗?(src / main / resources / schemas),因为我一直收到此消息:No XSD files found. Please check your plugin configuration.
zygimantus


7

最好的选择是%java_home%\bin\xjc -p [your namespace] [xsd_file].xsd

我也有一个问题,我们是否可以在这里进行逆向工程。如果是,我们可以从pojo类生成xsd吗?


xjc仅在java6中可用
sree

7

如果您不介意使用外部库,那么我过去曾使用Castor进行此操作。


如果使用Castor生成代码,事实发生之后,那些生成的类是否仍然依赖Caster?还是可以将这些类移动到没有Castor库的计算机上,它们仍然可以工作?
基思·帕尔默(Keith Palmer)2009年

不,生成的类不依赖于Castor库。
戴夫

是否有关于如何使用Castor做到这一点的好教程?看起来非常有前途……但是,至少可以说,Java不是我最强大的语言。我不确定我需要下载哪些Castor文件/软件包,以及如何实际执行代码生成...是否有逐步的新手示例?
基思·帕尔默(Keith Palmer)2009年

查阅此页面以获取有关如何使用Castor SourceGenerator类的文档:castor.org/sourcegen.html
Marc

2
看来,蓖麻长死了...文档链接都是404
帕维尔Veselov

5

JAXB限制。

我认为JAXB是一种处理XML和Java对象之间的数据的好方法。积极的一面是其经过验证的性能,并且在运行时可以更好地控制数据。充分利用内置工具或脚本,将节省大量编码工作。

我发现配置部分不是一项直接的任务,并且花费了数小时来进行开发环境的设置。

但是,由于遇到愚蠢的限制,我放弃了此解决方案。我的XML模式定义(XSD)具有名称为“值”的属性/元素,我必须原样使用XSD。这个很小的约束迫使我的绑定步骤XJC失败,并显示错误“已使用属性'值'”。

这是由于JAXB的实现,绑定过程试图通过在XSD之外创建Java对象,方法是为每个类添加少量属性,其中一个属性为value属性。当它处理我的XSD时,它抱怨已经有一个具有该名称的属性。


4

JAXB的XJC可以解决这个问题吗?我正在努力实现同样的目标。虽然仍处于“尝试”阶段。来到XJC,所以想到了分享。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.