从 .XSD 文件生成 Java 类...?
Posted
技术标签:
【中文标题】从 .XSD 文件生成 Java 类...?【英文标题】:Generate Java classes from .XSD files...? 【发布时间】:2010-10-15 17:55:18 【问题描述】:我有一个巨大的 QuickBooks SDK .XSD 架构文件,它定义了我可以从 QuickBooks 发送/接收的 XML 请求/响应。
我希望能够从这些 .XSD 文件轻松生成 Java 类,然后我可以使用这些类将 XML 编组为 Java 对象,并将 Java 对象编组为 XML。
有没有简单的方法来做到这一点...?
理想情况下,它在运行时不需要基本 Java 发行版之外的任何库。但我很灵活……
【问题讨论】:
如果要手动生成,请将 .xsd 文件放入 eclipse 项目中,右键单击该文件,然后点击“生成” 【参考方案1】:JAXB 完全符合您的要求。它从 1.6 开始内置到 JRE/JDK 中
【讨论】:
不幸的是,从 Java 9 开始,此功能将不再可用。这是因为所涉及的类(特别是 com.sun.tools.xjc.* 类)将不再通过JDK。 我不认为从 JDK 中删除它应该是一个问题,因为 java.net 项目(链接在答案中)可能会留下来。 作为explained here,您可以通过命令行参数在Java 9中添加依赖项,也可以手动添加依赖项。【参考方案2】:要扩展上面的“使用 JAXB”cmets,
在 Windows 中
"%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd
例如,
"%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd
稍等,如果您有一个格式良好的 XSD 文件,您将获得一些格式良好的 Java 类
【讨论】:
太好了,谢谢!要生成***类而不是封装,请参阅:***.com/questions/13175224/…。如果它导致类名冲突,请参阅:***.com/questions/13414407/…【参考方案3】:如果您想在 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's Blog 也是了解更多有关 JAXB 的好资源。对于这篇博文,我将向您展示如何使用 JAXB 进行简单的 Java-XML 序列化。
POJO 转 XML
假设我有一个 Item Java 对象。我想将 Item 对象序列化为 XML 格式。我首先要做的是使用 javax.xml.bind.annotation.* 包中的一些 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"));
完整的代码清单请参见代码清单 2main.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(...) 方法的参数(如
...
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 和文件的多种形式。同样,唯一的区别是方法参数:
...
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 对象。
【讨论】:
这看起来非常很有前途,并且比 JAXB 之类的大而复杂的东西更简单更好地满足我的需要。不幸的是,我看不到任何将现有的 .XSD 转换为 .class 文件的方法,而这正是我需要开始的。有没有办法做到这一点? 很遗憾,包含 JAXB 教程的博客已离线。 我们可以使用 jaxb2-maven-plugin 轻松完成,查看本教程journaldev.com/1312/… ""%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd" 有什么复杂之处?【参考方案4】:使用 Eclipse IDE:-
-
将 xsd 复制到新的/现有项目中。
确保您的类路径中有 JAXB 所需的 JAR。您可以下载一个here。
右键单击 XSD 文件 -> 生成 -> JAXB 类。
【讨论】:
【参考方案5】:最简单的方法是使用命令行。只需输入 .xsd 文件的目录:
xjc myFile.xsd.
所以,java 会生成所有的 Pojos。
【讨论】:
【参考方案6】:XMLBeans 会做到的。特别是“scomp”命令。
编辑:XMLBeans 一直是retired,查看this *** post 了解更多信息。
【讨论】:
是的,但是 XMLBeans 已经停产了。 ***.com/questions/27727546/… XMLBeans 重回正轨!【参考方案7】:Maven 可以用于此目的,您需要添加一些依赖项并清理您的应用程序。您将在目标文件夹中自动创建所有类。
只需将它们从目标复制到所需位置,这里是 pom.xml
,我用它来创建从 xsd
文件分类的文件:
<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 就会在编译时找到它们。
【讨论】:
这真的适用于资源目录吗? (src/main/resources/schemas),因为我不断收到这个:No XSD files found. Please check your plugin configuration.
【参考方案8】:
最好的选择是%java_home%\bin\xjc -p [your namespace] [xsd_file].xsd
。
我还有一个问题,如果我们可以选择在这里进行逆向工程。如果可以,我们可以从 pojo 类生成 xsd 吗?
【讨论】:
xjc 仅在 java6 中可用【参考方案9】:如果您不介意使用外部库,我过去曾使用 Castor 来执行此操作。
【讨论】:
如果使用 Castor 生成代码,这些生成的类是否仍然依赖于 Castor?或者我可以将这些类移到没有 Castor 库的机器上,它们仍然可以工作吗? 不,生成的类不依赖于 Castor 库。 有没有关于如何使用 Castor 做到这一点的好教程?它看起来很有前途……但至少可以说,Java 不是我最擅长的语言。我不确定我需要下载哪些 Castor 文件/包以及如何实际进行代码生成...周围有任何分步新手示例吗? 查看此页面以获取有关如何使用 Castor SourceGenerator 类的文档:castor.org/sourcegen.html 好像castor早就死了……文档链接都是404。【参考方案10】:JAXB 限制。
我曾在 JAXB 上工作,我认为它是处理 XML 和 Java 对象之间数据的好方法。积极的方面是它在运行时的性能和对数据的控制方面得到了证明并且更好。充分利用已构建的工具或脚本,可以省去大量的编码工作。
我发现配置部分不是一蹴而就的任务,并且花了几个小时来设置开发环境。
但是,由于我面临一个愚蠢的限制,我放弃了这个解决方案。我的 XML 模式定义 ( XSD ) 有一个名为“值”的属性/元素,我必须按原样使用 XSD。这个非常小的约束迫使我的绑定步骤 XJC 失败,并出现错误“Property 'Value' already used。”
这是由于 JAXB 实现,绑定过程尝试通过向每个类添加少量属性(其中一个是值属性)来从 XSD 创建 Java 对象。当它处理我的 XSD 时,它抱怨已经有一个具有该名称的属性。
【讨论】:
【参考方案11】:JAXB 的 XJC 不是对此的可能答案吗?我正在努力实现同样的目标。但仍处于“尝试”阶段。偶然发现了XJC,所以想到了分享。
【讨论】:
【参考方案12】:众所周知的JAXB
maven plugin 可以在您想要的任何构建阶段为您执行此操作。
你可以用两种方式来做这些事情:xsd Java
【讨论】:
【参考方案13】:谈到 JAXB 限制,当不同属性具有相同名称时,一个解决方案是向 xsd 添加内联 jaxb 自定义:
+
. . 有约束力的声明 . .
或外部自定义...
您可以查看更多信息: http://jaxb.java.net/tutorial/section_5_3-Overriding-Names.html
【讨论】:
以上是关于从 .XSD 文件生成 Java 类...?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 Qt(不使用 XSD 工具)从 xsd 生成 C++ 类?