JAXB 选择列表

发布于 2024-07-20 10:55:16 字数 967 浏览 14 评论 0 原文

我有以下模式

<complexType name="BookShelf">
   <sequence>
      <element name="newBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
      <element name="oldBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
   </sequence>
</complexType>

XJC 生成带有两个列表的 BookShelf 类,一个用于 newBook,一个用于 oldBook。 出色的!

现在我希望书籍以任何顺序出现。 因此,我将架构重写为:

<complexType name="BookShelf">
   <sequence>
      <choice minOccurs="0" maxOccurs="unbounded">
         <element name="newBook" type="string"/>
         <element name="oldBook" type="string"/>
      </choice>
   </sequence>
</complexType>

但现在 XJC 生成的 BookShelf 仅包含一个类型为 List> 的列表 newBookOrOldBook。

我不关心书籍出现的顺序,我希望允许 XML 编写者按照他/她希望的任何顺序指定书籍,但我仍然希望每种类型的书籍作为生成的 BookShelf 类中的列表。 我有什么办法可以实现这个目标吗?

I have following schema

<complexType name="BookShelf">
   <sequence>
      <element name="newBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
      <element name="oldBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
   </sequence>
</complexType>

XJC generates BookShelf class with two lists, one for newBook and one for oldBook. Excellent!

Now I want books to appear in any order. So I rewrite my schema to:

<complexType name="BookShelf">
   <sequence>
      <choice minOccurs="0" maxOccurs="unbounded">
         <element name="newBook" type="string"/>
         <element name="oldBook" type="string"/>
      </choice>
   </sequence>
</complexType>

But now XJC generates BookShelf with only one list newBookOrOldBook of type List<JAXBElement<String>>.

I don't care about the order in which books appear and I want to allow XML writer to specify books in any order he\she wishes, but I still want books of each type as List in generated BookShelf class. Is there any way I can achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等风也等你 2024-07-27 10:55:16

您可以使用 Simplify 插件 ://github.com/highsource/jaxb2-basics" rel="nofollow">JAXB2 基础知识。 它可以简化 @XmlElements@XmlElementRefs 属性,如果您并不真正关心顺序,这会使事情变得容易得多。 下面是一个示例(摘自文档):

考虑以下选择:

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType"/>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

这通常会生成如下属性:

@XmlElementRefs({
    @XmlElementRef(name = "a", type = JAXBElement.class),
    @XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;

您可以使用 simplify:as-element-property 元素将此复杂属性重新建模为两个元素properties 或 simplify:as-reference-property 作为两个引用属性。

并非如此,在引用属性的情况下,您必须自定义 xs:element 之一,而不是 xs:choice

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType">
            <xs:annotation>
                <xs:appinfo>
                    <simplify:as-element-property/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

结果是:

@XmlElement(name = "a")
protected List<SomeType> a;
@XmlElement(name = "b")
protected List<SomeType> b;

You can use the Simplify plugin from JAXB2 Basics. It can simplify @XmlElements and @XmlElementRefs properties, which makes things a lot easier, if you don't really care about the order. Here's an example (excerpt from the documentation):

Consider the following choice:

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType"/>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

This will normally generate a property like:

@XmlElementRefs({
    @XmlElementRef(name = "a", type = JAXBElement.class),
    @XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;

You can use the simplify:as-element-property element to remodel this complex property as two element properties or simplify:as-reference-property as two reference properties.

Not that in the case of a reference property, you have to customize one of the xs:element and not the xs:choice.

<xs:complexType name="typeWithReferencesProperty">
    <xs:choice maxOccurs="unbounded">
        <xs:element name="a" type="someType">
            <xs:annotation>
                <xs:appinfo>
                    <simplify:as-element-property/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <xs:element name="b" type="someType"/>
    </xs:choice> 
</xs:complexType>

Results in:

@XmlElement(name = "a")
protected List<SomeType> a;
@XmlElement(name = "b")
protected List<SomeType> b;
坏尐絯℡ 2024-07-27 10:55:16

也许是这样的?

<schema 
   elementFormDefault = "qualified" 
   xmlns              = "http://www.w3.org/2001/XMLSchema"
   xmlns:xs           = "http://www.w3.org/2001/XMLSchema"
   xmlns:tns          = "urn:cheeso.examples.2009.05.listofbooks" 
   targetNamespace    = "urn:cheeso.examples.2009.05.listofbooks" 
  >

  <element name="Shelf" nillable="true" type="tns:BookShelf" />

  <complexType name="BookShelf">
    <sequence>
      <element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
    </sequence>
  </complexType>

  <complexType name="ArrayOfChoice1">
    <choice minOccurs="0" maxOccurs="unbounded">
      <element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="tns:newBook" />
      <element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="tns:oldBook" />
    </choice>
  </complexType>

  <complexType name="Book">
    <attribute name="name" type="string" />
  </complexType>

  <complexType name="newBook">
    <complexContent mixed="false">
      <extension base="tns:Book" />
    </complexContent>
  </complexType>

  <complexType name="oldBook">
    <complexContent mixed="false">
      <extension base="tns:Book" />
    </complexContent>
  </complexType>

</schema>

当然你可以简化为

<schema 
   elementFormDefault = "qualified" 
   xmlns              = "http://www.w3.org/2001/XMLSchema"
   xmlns:xs           = "http://www.w3.org/2001/XMLSchema"
   xmlns:tns          = "urn:cheeso.examples.2009.05.listofbooks" 
   targetNamespace    = "urn:cheeso.examples.2009.05.listofbooks" 
  >

  <element name="Shelf" nillable="true" type="tns:BookShelf" />

  <complexType name="BookShelf">
    <sequence>
      <element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
    </sequence>
  </complexType>

  <complexType name="ArrayOfChoice1">
    <choice minOccurs="0" maxOccurs="unbounded">
      <element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="xs:string" />
      <element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="xs:string" />
    </choice>
  </complexType>

</schema>

Maybe something like this?

<schema 
   elementFormDefault = "qualified" 
   xmlns              = "http://www.w3.org/2001/XMLSchema"
   xmlns:xs           = "http://www.w3.org/2001/XMLSchema"
   xmlns:tns          = "urn:cheeso.examples.2009.05.listofbooks" 
   targetNamespace    = "urn:cheeso.examples.2009.05.listofbooks" 
  >

  <element name="Shelf" nillable="true" type="tns:BookShelf" />

  <complexType name="BookShelf">
    <sequence>
      <element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
    </sequence>
  </complexType>

  <complexType name="ArrayOfChoice1">
    <choice minOccurs="0" maxOccurs="unbounded">
      <element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="tns:newBook" />
      <element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="tns:oldBook" />
    </choice>
  </complexType>

  <complexType name="Book">
    <attribute name="name" type="string" />
  </complexType>

  <complexType name="newBook">
    <complexContent mixed="false">
      <extension base="tns:Book" />
    </complexContent>
  </complexType>

  <complexType name="oldBook">
    <complexContent mixed="false">
      <extension base="tns:Book" />
    </complexContent>
  </complexType>

</schema>

Of course you could simplify to

<schema 
   elementFormDefault = "qualified" 
   xmlns              = "http://www.w3.org/2001/XMLSchema"
   xmlns:xs           = "http://www.w3.org/2001/XMLSchema"
   xmlns:tns          = "urn:cheeso.examples.2009.05.listofbooks" 
   targetNamespace    = "urn:cheeso.examples.2009.05.listofbooks" 
  >

  <element name="Shelf" nillable="true" type="tns:BookShelf" />

  <complexType name="BookShelf">
    <sequence>
      <element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
    </sequence>
  </complexType>

  <complexType name="ArrayOfChoice1">
    <choice minOccurs="0" maxOccurs="unbounded">
      <element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="xs:string" />
      <element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="xs:string" />
    </choice>
  </complexType>

</schema>
隱形的亼 2024-07-27 10:55:16

我认为如果不编写一些自定义 java 或 XSLT,这在 JAXB 中是不可能的。

JAXB 不太擅长在具有不同结构(如您的结构)的对象和 xml 之间进行映射。 此外,当转换为 Java 中的两个单独的列表时,XML 中旧书相对于新书的排序将会丢失,并且 JAXB 通常希望保留信息。

以下内容没有回答您的问题,但也许这是朝着您想要的迈出的一步:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="bookShelf" type="BookShelf"/>
  <xs:complexType name="BookShelf">
    <xs:sequence>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element name="newBook" minOccurs="0" type="xs:string"/>
        <xs:element name="oldBook" minOccurs="0" type="xs:string"/>
      </xs:sequence>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

我还没有尝试过使用 JAXB,但我认为它会生成一个列表具有两个字段的newBookoldBook。 因此,您不必强制转换或使用instanceof,而只需检查null 即可查看它是哪一个。 正如我所说,这不是一个解决方案,但可能更接近一点。

I don't think this is possible in JAXB, without writing some custom java or XSLT.

JAXB isn't very good at mapping between objects and xml that have different structure, like yours. Also, the ordering of the old book with respect to new books in XML would be lost when converted to two separate lists in Java, and JAXB generally wants to preserve information.

The following does not answer your question, but maybe it's a step towards what you want:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="bookShelf" type="BookShelf"/>
  <xs:complexType name="BookShelf">
    <xs:sequence>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element name="newBook" minOccurs="0" type="xs:string"/>
        <xs:element name="oldBook" minOccurs="0" type="xs:string"/>
      </xs:sequence>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

I haven't tried this with JAXB, but I think it will generate a list of a class with two fields, newBook and oldBook. So, you don't have to cast or use instanceof, but can just check for null to see which one it is. As I said, it's not a solution, but maybe a little bit closer.

殊姿 2024-07-27 10:55:16

我认为我必须拒绝在一个元素中混合不同元素的列表(在书本上混合新旧书籍)的想法,特别是因为我计划在其他元素中引用这些元素的列表(新书和旧书列表) 。 如果我不这样做,它很快就会成为 Java 代码中的一场噩梦。 我以以下模式结束:

<schema
   xmlns="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://www.example.org/books"
   targetNamespace="http://www.example.org/books"
   elementFormDefault="qualified"
>
   <complexType name="BookShelf">
      <sequence>
         <element name="newBooks" type="tns:NewBookList" minOccurs="0" />
         <element name="oldBooks" type="tns:OldBookList" minOccurs="0" />
      </sequence>
   </complexType>

   <complexType name="NewBookList">
      <sequence>
         <element name="newBook" type="tns:NewBook" maxOccurs="unbounded" />
      </sequence>
   </complexType>

   <complexType name="OldBookList">
      <sequence>
         <element name="oldBook" type="tns:OldBook" maxOccurs="unbounded" />
      </sequence>
   </complexType>

   <complexType name="NewBook" />
   <complexType name="OldBook" />
</schema>

感谢大家帮助我实现这一点。 这种模式将导致更清晰和简单的 Java 代码以及更易读和可预测的 XML 文档。

I think I have to refuse the idea of mixing lists of different elements in one element (mixing old and new books on a bookself), especially because I'm planning to reference lists of those elements (new and old books lists) in other elements. If I don't it quickly became a nightmare in java code. I ended with the following schema:

<schema
   xmlns="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://www.example.org/books"
   targetNamespace="http://www.example.org/books"
   elementFormDefault="qualified"
>
   <complexType name="BookShelf">
      <sequence>
         <element name="newBooks" type="tns:NewBookList" minOccurs="0" />
         <element name="oldBooks" type="tns:OldBookList" minOccurs="0" />
      </sequence>
   </complexType>

   <complexType name="NewBookList">
      <sequence>
         <element name="newBook" type="tns:NewBook" maxOccurs="unbounded" />
      </sequence>
   </complexType>

   <complexType name="OldBookList">
      <sequence>
         <element name="oldBook" type="tns:OldBook" maxOccurs="unbounded" />
      </sequence>
   </complexType>

   <complexType name="NewBook" />
   <complexType name="OldBook" />
</schema>

Thanks everyone for helping me realize this. This schema will lead to more clear and simple Java code as well as to more readable and predictable XML document.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文