从.XSD 文件生成 Java 类... ?

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

我希望能够从这些类轻松地生成 Java 类。XSD 文件,然后我可以使用这些文件将 XML 封送到 Java 对象,将 Java 对象封送到 XML。

有什么简单的方法吗?

理想情况下,它在运行时不需要基本 Java 发行版之外的任何库。

347321 次浏览

XMLBeans 将执行此操作,特别是“ scomp”命令。

编辑: XMLBeans 已经是 退休了,请查看 这个堆栈溢出邮件以获得更多信息。

JAXB 可以完全满足您的需要,它从1.6开始内置在 JRE/JDK 中

如果您不介意使用外部库,我过去曾使用 卡斯特来完成这项工作。

著名的 JAXB

有一个 Maven 插件可以在您想要的任何构建阶段为您做到这一点。

您可以通过两种方式来完成这项工作: xsd <-> Java

如果您想在不到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 的博客也是了解 JAXB 的一个很好的资源。对于这个博客条目,我将向您展示如何使用 JAXB 进行简单的 Java-XML 序列化。

POJO 到 XML

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

从代码

  • @XmlRootElement(name="Item")表示我想成为根元素。
  • @XmlType(propOrder = {"name", "price"})表示我希望元素在 XML 输出中的排列顺序。
  • @XmlAttribute(name="id", ...)表示 id 是根元素的属性。
  • @XmlElement(....)表示我希望 price 和 name 成为 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>

很简单吧?您也可以将输出 XML 通过文本 String、 Stream、 Writer、 ContentHandler 等方式传送,只需更改 Marshall (...)方法的参数,如

...
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(void _ 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’属性更改为 string 而不是 int。

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

JAXB 的 XJC 不就是这个问题的可能答案吗?我也在努力实现同样的目标。不过还在“尝试”阶段。偶然发现 XJC,所以想到分享。

JAXB 限制。

我致力于 JAXB,因为根据我的观点,它是处理 XML 和 Java 对象之间数据的一种很好的方法。积极的一面是经过验证的,在运行时的性能和对数据的控制方面更好。随着构建工具或脚本的良好使用,它将带走大量的编码工作。

我发现配置部分并不是一项立竿见影的任务,我花了很多时间来设置开发环境。

然而,我放弃了这个解决方案,因为我面临一个愚蠢的限制。我的 XML 模式定义(XSD)有一个名为“ value”的属性/元素,我必须按原样使用 XSD。这个非常小的约束迫使我的绑定步骤 XJC 失败,并出现“ Property‘ Value’already used”错误

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

谈到 JAXB 限制,对不同属性使用相同名称时的一种解决方案是向 xsd 添加内联 JAXB 定制:

+

. . 有约束力的声明 . .

或者外部定制。

你可参阅以下资料: Http://jaxb.java.net/tutorial/section_5_3-overriding-names.html

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

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

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

稍等一下,如果您有一个格式良好的 XSD 文件,您将得到一些格式良好的 Java 类

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

我还有个问题我们是否可以选择在这里做逆向工程。如果是,我们可以从 pojo 类生成 xsd 吗?

使用 Eclipse IDE:-

  1. 将 xsd 复制到一个新的/现有的项目中。
  2. 确保类路径中有 JAXB 所需的 JAR。
  3. 右键单击 XSD 文件-> Generate-> JAXB 类。

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>

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

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

xjc myFile.xsd.

因此,java 将生成所有 Pojos。