使用 XJC 将 XML 模式转换为 Java 类

发布于 2024-08-31 01:36:25 字数 1701 浏览 9 评论 0 原文

我正在使用 xjc 从 XML 模式生成 Java 类,以下是 XSD 的摘录。

<xs:element name="NameInfo">
  <xs:complexType>
    <xs:sequence>
      <xs:choice>
        <xs:element ref="UnstructuredName"/> <!-- This line -->
        <xs:sequence>
          <xs:element ref="StructuredName"/>
          <xs:element ref="UnstructuredName" minOccurs="0"/> <!-- and this line! -->
        </xs:sequence>
      </xs:choice>
      <xs:element ref="SomethingElse" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

在大多数情况下,生成的类都很好,但对于上面的块,我会得到类似的内容:

public List<Object> getContent() {
  if (content == null) {
    content = new ArrayList<Object>();
  }
  return this.content;
}

上面有以下注释:

* You are getting this "catch-all" property because of the following reason: 
* The field name "UnstructuredName" is used by two different parts of a schema. See: 
* line XXXX of file:FILE.xsd
* line XXXX of file:FILE.xsd
* To get rid of this property, apply a property customization to one 
* of both of the following declarations to change their names: 
* Gets the value of the content property.

我在有问题的两行末尾放置了注释。

目前,我认为更改架构并不容易,因为这是供应商之间决定的,我不想走这条路(如果可能的话),因为它会大大减慢进度。

我搜索并发现 此页面,是外部定制我想做什么?我主要处理生成的类,因此我并不完全熟悉生成这些类的过程。一个简单的“属性定制”例子就太好了!只要模式仍然可以使用,生成 Java 类的替代方法就可以了。

编辑:我应该澄清这两个 UnstructedName 确实是相同的元素。

I am using xjc to generate Java classes from the XML schema and the following is an excerpt of the XSD.

<xs:element name="NameInfo">
  <xs:complexType>
    <xs:sequence>
      <xs:choice>
        <xs:element ref="UnstructuredName"/> <!-- This line -->
        <xs:sequence>
          <xs:element ref="StructuredName"/>
          <xs:element ref="UnstructuredName" minOccurs="0"/> <!-- and this line! -->
        </xs:sequence>
      </xs:choice>
      <xs:element ref="SomethingElse" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

For the most part the generated classes are fine but for the above block I would get something like:

public List<Object> getContent() {
  if (content == null) {
    content = new ArrayList<Object>();
  }
  return this.content;
}

with the following comment above it:

* You are getting this "catch-all" property because of the following reason: 
* The field name "UnstructuredName" is used by two different parts of a schema. See: 
* line XXXX of file:FILE.xsd
* line XXXX of file:FILE.xsd
* To get rid of this property, apply a property customization to one 
* of both of the following declarations to change their names: 
* Gets the value of the content property.

I have placed a comment at the end of the two line in question.

At the moment, I don't think it will be easy to change the schema since this was decided between vendors and I would not want to go this route (if possible) as it will slow down progress quite a bit.

I searched and have found this page, is the external customization what I want to do? I have been mostly working with the generated classes so I'm not entirely familiar with the process that generates these classes. A simple example of the "property customization" would be great! Alternative method of generating the Java classes would be fine as long as the schema can still be used.

EDIT: I should clarify that the two UnstructuredName are indeed the same element.

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

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

发布评论

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

评论(4

脸赞 2024-09-07 01:36:25

您还可以使用名为 的绑定自定义:

<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:version="2.0">
        <jxb:globalBindings>
            <xjc:simple />
        </jxb:globalBindings>
</jxb:bindings>

但是请注意,这是特定于供应商的(尽管他们使用 XJC 之外的其他东西;) )

更多信息 此处

You can also use a binding customization called <xjc:simple />:

<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:version="2.0">
        <jxb:globalBindings>
            <xjc:simple />
        </jxb:globalBindings>
</jxb:bindings>

Please however be adviced that this is vendor specific (who uses something else than XJC though ;) )

More Info here

豆芽 2024-09-07 01:36:25

这里的基本问题是您有一个由 组成的 ,它在 Java 中翻译为“一个 List” 的事物”。 Java 的类型结构不够灵活,无法更好地表示这一点。

绑定自定义可能可以帮助您,但在这种情况下,我怀疑不会,因为我看不到更好的方法来表示此信息。

我过去使用的另一种技术是首先通过简单的 XSLT 转换传递模式,将组件重新排列为更 JAXB 友好的内容,同时仍然允许文档具有实际的相同结构。这样,您可以“更改”架构而不更改原始架构。

The essential problem here is that you have a <xs:sequence> consisting of an <xs:choice>, which translates in Java to "a List of things". Java's type structure isn't flexible enough to represent this any better.

A binding customisation might help you, but in this case, I suspect not, since I can't see a better way to represent this information.

An alternative technique I've used in the past is to pass the schema through a simple XSLT transformation first, re-arranging the components into something more JAXB-friendly, while still permitting the same structures the documents will have in reality. This way, you can "change" the schema without changing the original.

俏︾媚 2024-09-07 01:36:25

我也有同样的问题。我切换到 xmlbeans 和 axis。 XMLBeans 可以毫无问题且轻松地编译您的模式。 JaxB 无法处理这个问题。为了让 JaxB 处理这个问题,您可以稍微改变一下您的模式。

  <xs:sequence>
          <xs:choice>
    <!-- changed the following line -->
            <xs:element name="UnstructuredTop" type="UnstructuredName"/> 
    <!-- end of change -->
            <xs:sequence>
              <xs:element ref="StructuredName"/>
              <xs:element ref="UnstructuredName" minOccurs="0"/>
            </xs:sequence>
          </xs:choice>
          <xs:element ref="SomethingElse" minOccurs="0"/>
    </xs:sequence>

然后 JaxB 会区分两者并且不会崩溃。

不过你的情况和我的情况一样。改变模式是不可能的。所以我选择了 xmlBeans 和 axis (which sux)。

I have had the same issue. I switched to xmlbeans and axis. XMLBeans can compile your schema without issue and without headache. JaxB can't handle this. In order to make JaxB handle this, you could change your schema a little.

  <xs:sequence>
          <xs:choice>
    <!-- changed the following line -->
            <xs:element name="UnstructuredTop" type="UnstructuredName"/> 
    <!-- end of change -->
            <xs:sequence>
              <xs:element ref="StructuredName"/>
              <xs:element ref="UnstructuredName" minOccurs="0"/>
            </xs:sequence>
          </xs:choice>
          <xs:element ref="SomethingElse" minOccurs="0"/>
    </xs:sequence>

Then JaxB will distinguish the two and not flip out.

However your situation is like my situation. Changing the schema was out of the question. So I went with xmlBeans and axis (which sux).

笑看君怀她人 2024-09-07 01:36:25

我创建了一个包装类来解决这个问题:

List<JAXBElement<?>> contentList = address.getContent();
if (contentList != null && contentList.size() > 0) {
    Address4JaxbMula address4JaxbMula = new Address4JaxbMula(contentList);

...
}

...

public static class Address4JaxbMula {
    public CountryCodeType countryCode;
    public AddressFixType addressFix;
    public String addressFree;

    public Address4JaxbMula(List<JAXBElement<?>> contentList) {
        if (contentList != null && contentList.size() > 0) {
            for (JAXBElement<?> content : contentList) {
                Object value = content.getValue();
                if (value.getClass().isAssignableFrom(CountryCodeType.class)) {
                    countryCode = (CountryCodeType) content.getValue();
                } else if (value.getClass().isAssignableFrom(AddressFixType.class)) {
                    addressFix = (AddressFixType) content.getValue();
                } else {
                    addressFree = (String) value;
                }
            }
        }
    }

}

I created a wrapper class to solve the problem:

List<JAXBElement<?>> contentList = address.getContent();
if (contentList != null && contentList.size() > 0) {
    Address4JaxbMula address4JaxbMula = new Address4JaxbMula(contentList);

...
}

...

public static class Address4JaxbMula {
    public CountryCodeType countryCode;
    public AddressFixType addressFix;
    public String addressFree;

    public Address4JaxbMula(List<JAXBElement<?>> contentList) {
        if (contentList != null && contentList.size() > 0) {
            for (JAXBElement<?> content : contentList) {
                Object value = content.getValue();
                if (value.getClass().isAssignableFrom(CountryCodeType.class)) {
                    countryCode = (CountryCodeType) content.getValue();
                } else if (value.getClass().isAssignableFrom(AddressFixType.class)) {
                    addressFix = (AddressFixType) content.getValue();
                } else {
                    addressFree = (String) value;
                }
            }
        }
    }

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