【问题标题】:How to generate @XmlRootElement Classes for Base Types in XSD?如何为 XSD 中的基本类型生成 @XmlRootElement 类?
【发布时间】:2010-12-03 14:26:09
【问题描述】:

我在使用 XJC 从 XSD 生成带有适当 JAXB 注释的 Java 类时遇到一些问题。

我有一个相对简单的 XSD 文件来定义我的 XML 架构。 XSD 中的复杂类型利用<xs:extension> 标签的继承优势。我遇到的问题是我需要所有复杂类型来生成带有@XmlRootElement 的Java 类。

不幸的是,XJC 生成类的方式意味着只有派生类获得@XmlRootElement(而不是基类)。我正在使用简单的全局绑定指令来确保它解决了我在使用 XJC 时遇到的许多其他问题。

这是 XSD 的一个示例 sn-p:

<xs:schema version="1.0" targetNamespace="http://www.knowledgemill.com/kmcs"
  xmlns:kmcs="http://www.knowledgemill.com/kmcs"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  jaxb:version="2.0"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  jaxb:extensionBindingPrefixes="xjc"
  elementFormDefault="qualified">
    <xs:annotation>
        <xs:appinfo>
            <jaxb:globalBindings>
                <xjc:simple />
            </jaxb:globalBindings>
        </xs:appinfo>
    </xs:annotation>

    <xs:element name="Artifact" type="kmcs:Artifact"/>
    <xs:element name="EmailArtifact" type="kmcs:EmailArtifact"/>

    <xs:complexType name="Artifact">
        <xs:sequence>
            <xs:element name="artifactId" type="xs:string" minOccurs="0"/>
            <xs:element name="artifactType" type="xs:string" minOccurs="0"/>
            <xs:element name="contentHash" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="EmailArtifact">
        <xs:complexContent>
            <xs:extension base="kmcs:Artifact">
                <xs:sequence>
                    <xs:element name="subject" type="xs:string" minOccurs="0"/>
                    <xs:element name="threadSubject" type="xs:string" minOccurs="0"/>
                    <xs:element name="from" type="xs:string" minOccurs="0"/>
                    <xs:element name="to" type="xs:string" minOccurs="0"/>
                    <xs:element name="cc" type="xs:string" minOccurs="0"/>
                    <xs:element name="bcc" type="xs:string" minOccurs="0"/>
                    <xs:element name="messageId" type="xs:string" minOccurs="0"/>
                    <xs:element name="date" type="xs:date" minOccurs="0"/>
                    <xs:element name="size" type="xs:long" minOccurs="0"/>
                    <xs:element name="hasAttachment" type="xs:boolean" minOccurs="0"/>
                    <xs:element name="sensitivity" type="xs:string" minOccurs="0"/>
                    <xs:element name="headerHash" type="xs:string" minOccurs="0"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>


</xs:schema>

从上面的 sn-p 可以看出,EmailArtifact 扩展了Artifact

EmailArtifact 的 java 类代码包含以下内容:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "EmailArtifact", propOrder = {
    "subject",
    "threadSubject",
    "from",
    "to",
    "cc",
    "bcc",
    "messageId",
    "date",
    "size",
    "hasAttachment",
    "sensitivity",
    "headerHash"
})
@XmlSeeAlso({
    ExtendedEmail.class
})
@XmlRootElement(name = "EmailArtifact")
public class EmailArtifact
    extends Artifact
{

    protected String subject;
    protected String threadSubject;
    protected String from;
    protected String to;
    protected String cc;
    protected String bcc;
    protected String messageId;
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar date;
    protected Long size;
    protected Boolean hasAttachment;
    protected String sensitivity;
    protected String headerHash;

Artifact 的 java 类代码包含以下内容:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Artifact", propOrder = {
    "artifactId",
    "artifactType",
    "contentHash"
})
@XmlSeeAlso({
    ManagedDocArtifact.class,
    EmailArtifact.class
})
public class Artifact {

    protected String artifactId;
    protected String artifactType;
    protected String contentHash;

EmailArtifact 中,我们可以看到它包含@XmlRootElement,但基本类型Artifact 不包含@XmlRootElement

如何强制 XJC 为所有类(包括基类型)生成 @XmlRootElement

【问题讨论】:

  • 简单绑定模式应该做到这一点。你确定你指定的正确吗?
  • 是的,我很有信心 - 这是我的 XSD 的顶部以及相关的 globalBindings... w3.org/2001/XMLSchema" xmlns:jaxb="java.sun.com/xml/ns/jaxb" jaxb:version="2.0" xmlns:xjc="java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" >
  • 是的,我认为应该可以,虽然我一直使用外部绑定自定义而不是内联自定义
  • 感谢您的回复。还尝试使用外部绑定文件。再次......没有运气。令人沮丧的一个。也许这是我遗漏的标准的一部分,即基类型永远不应该是 XmlRootElement。不过,这似乎是一种奇怪的做法……哦,好吧。目前,我不得不求助于在一代之后手动将它们重新添加 - 不好:-(有点违背了将 XSD 保持为事实来源的观点。
  • 试试jaxb.dev.java.net上的邮件列表,你可能会得到更集中的答案。

标签: java xsd jaxb xjc


【解决方案1】:

使用 xjb-file 绑定即可:

<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
    <jxb:globalBindings>
      <xjc:simple />
    </jxb:globalBindings>
  </jxb:bindings>
</jxb:bindings>

别忘了定义相同类型的元素:

<xs:complexType name="Artifact" />
<xs:element name="artifact" type="Artifact">

【讨论】:

  • 谢谢!这是最好的解决方案。这不需要更改 xsd 架构,也不需要更改生成的根类。
  • 你能解释一下关于需要定义和元素相同类型的第二部分吗?这是在哪里定义的?我希望不要更改 XSD 或生成的类。
  • 这对我也有用。 jxb:bindings 中的两个属性都不是必需的。另外,我必须为 xjc 编译器提供 extension=true 命令行参数(在 Ant 脚本中)。
  • 请注意,java 9 版本的 jaxb(至少是 jaxb2-maven-plugin:2.4)有一个错误,它会忽略 xjb 文件中的此类语句(在撰写本文时)。见github.com/highsource/maven-jaxb2-plugin/issues/120
【解决方案2】:

question 引用了 Kohsuke Kawaguchi 的 blog 帖子,他曾在 JAX-B 或 JAX-WS RI 工作,其中谈到了 RI 的决策过程以及规范中对此问题缺乏明确性。

博文提到简单绑定功能是 RI 的一部分。您是否使用 RI 生成代码?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 2010-09-20
    相关资源
    最近更新 更多