1

我是 XSD 设计和 JAXB 的新手。我设法创建了我的 XSD,如下所示:

<xsd:element name="policy" >
<xsd:complexType>
    <xsd:sequence>
        <xsd:element name="actor-def" type="tns:actor-def"/>                        
        <xsd:element name="actor-system-def" type="tns:actor-system-def"/>           
        </xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="actor-def">
    <xsd:sequence>
        <xsd:element name="actor-system" type="tns:actor-system-type"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:ID" use="required" />
</xsd:complexType>
<xsd:complexType name="actor-system-type">
    <xsd:attribute name="name" type="xsd:IDREF" use="required" />
</xsd:complexType>

<xsd:complexType name="actor-system-def">
    <xsd:attribute name="name" type="xsd:ID" use="required" />
    <xsd:attribute name="url" type="xsd:anyURI" use="required" />
</xsd:complexType>

基本上,我有一个“policy”的根元素,它允许定义几个“actor-def”和“actor-system-def”。每个“actor-def”都属于一个使用 ID 和 IDREF 实现的“actor-system-def”。

为了使用 JAXB,我使用 Eclipse 的 JAXB Classes for Schema 创建工具自动创建了所有必需的类。它会根据 XSD 文件自动创建以下类:

策略.java

ActorDef.java

ActorSystemDef.java

ActorSystemType.java

除了 ActorDef.java 文件和其中使用 XSD 文件中的 IDREF 定义的 actorSystem 变量的类型之外,一切看起来都很好。基本上,ActorDef.java 文件具有以下内容:

@XmlElement(name = "actor-system", required = true)
protected ActorSystemType actorSystem;
public ActorSystemType getActorSystem() {
    return actorSystem;
}

这样做的问题是,由于从 ActorDef.getActorSystem() 返回的类型是 ActorSystemType 类型,它是对错误对象的引用。我想要的是对相关 ActorSystemDef 的引用,以便我可以调用 getName() 方法来获取 ActorSystemDef 的名称(如下所示)

JAXBContext myJAXBContext = JAXBContext.newInstance("spec_jaxb");
Unmarshaller myUnmarshaller = myJAXBContext.createUnmarshaller();
Policy myPolicy = (Policy) myUnmarshaller.unmarshal(new  File("src/main/java/spec/private_policy.xml"));

List<ActorDef> actorList = myPolicy.getActorDef();
for (ActorDef actor : actorList) {
    System.out.println(actor.getActorSystem().getName());
}

我能够通过手动修改由 JAXB 工具自动创建的类来使代码工作。我将 ActorDef.java 中的 actorSystem 变量的类型更改为 ActorSystemDef,如下所示:

protected ActorSystemDef actorSystem;
public ActorSystemDef getActorSystem() {
    return actorSystem;
}

这解决了问题,代码工作正常,但我想了解如何更正我的 XSD 文件,以便 JAXB 类创建工具自动更正上述问题。我认为我在导致此问题的 XSD 定义中犯了一个错误。我经常修改我的 XSD 文件,不能每次都手动进行所有这些更改。

4

2 回答 2

1

我尝试了您的架构,并获得了ActorDef与您相同的课程:

@XmlElement(name = "actor-system", required = true)
protected ActorSystemType actorSystem;

public ActorSystemType getActorSystem() { return actorSystem; }
public void setActorSystem(ActorSystemType value) { this.actorSystem = value; }

但是后来我删除了你架构的这一部分(因为你似乎没有使用它 - 为什么它在那里?):

<xsd:complexType name="actor-system-type">
    <xsd:attribute name="name" type="xsd:IDREF" use="required" />
</xsd:complexType>

然后将actor-system元素type从:

<xsd:element name="actor-system" type="tns:actor-system-type"/>

至:

<xsd:element name="actor-system" type="tns:actor-system-def"/>

因此,结束模式变为:

<xsd:element name="policy">
<xsd:complexType>
    <xsd:sequence>
        <xsd:element name="actor-def" type="tns:actor-def"/>
        <xsd:element name="actor-system-def" type="tns:actor-system-def"/>
    </xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="actor-def">
    <xsd:sequence>
        <xsd:element name="actor-system" type="tns:actor-system-def"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:ID" use="required" />
</xsd:complexType>

<xsd:complexType name="actor-system-def">
    <xsd:attribute name="name" type="xsd:ID" use="required" />
    <xsd:attribute name="url" type="xsd:anyURI" use="required" />
</xsd:complexType>

然后使用这个,我生成了类并得到了,对于ActorDef,这个:

@XmlElement(name = "actor-system", required = true)
protected ActorSystemDef actorSystem;

public ActorSystemDef getActorSystem() { return actorSystem; }
public void setActorSystem(ActorSystemDef value) { this.actorSystem = value; }

在我看来,这就是你一开始所期待的,对吧?

此外,应该是,ActorSystemType.java不再生成。

于 2013-04-17T04:03:24.443 回答
0

@acdcjunior:根据我的最后一条评论,您提供的解决方案将不允许这样的代码:

  <tns:actor-def>
    <tns:name>actor1</tns:name>
    <tns:description>actor 1 desc</tns:description>
    <tns:type>local</tns:type>
    <tns:actor-reference>www.actor.com</tns:actor-reference>
    <tns:actor-system>
      <tns:name>actor-system-1</tns:name>
    </tns:actor-system>
  </tns:actor-def>
  <tns:actor-system-def>
    <tns:name>actor-system-1</tns:name>
    <tns:description>actor-system-1 desc</tns:description>
    <tns:url>http://actorsystem1.org</tns:url>
    <tns:port>80</tns:port>
  </tns:actor-system-def>

事实上,如果 actor-system-1 已经定义,它就不允许引用它。相反,您必须从 actor-def 中创建一个新的 actor-system。

我能够通过更改您的代码来解决问题,如下所示:

<xsd:element name="policy">
<xsd:complexType>
    <xsd:sequence>
        <xsd:element name="actor-def" type="tns:actor-def"/>
        <xsd:element name="actor-system-def" type="tns:actor-system-def"/>
    </xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="actor-def">
    <xsd:sequence>
        <xsd:element name="actor-system" type="xsd:IDREF"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:ID" use="required" />
</xsd:complexType>

<xsd:complexType name="actor-system-def">
    <xsd:attribute name="name" type="xsd:ID" use="required" />
    <xsd:attribute name="url" type="xsd:anyURI" use="required" />
</xsd:complexType>

现在创建 JAXB 类时,我只有 ActorDef.java 和 ActorSystemDef.java 并且 ActorDef.getActorSystem() 的代码如下所示:

@XmlElement(name = "actor-system", required = true)
@XmlIDREF
@XmlSchemaType(name = "IDREF")
protected Object actorSystem;    

public Object getActorSystem() {
        return actorSystem;
    }

可以使用强制转换轻松地将其转换为 ActorSystemDef 对象:

system.out.println(   ((ActorSystemDef) actor.getActorSystem()).getName()  );
于 2013-04-18T00:05:56.920 回答