java JAXB 类型问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/790118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:47:39  来源:igfitidea点击:

JAXB Types problem

javaxmlcode-generationjaxb

提问by Ricardo Figueroa

I have an xsd that looks like this (snippet):

我有一个看起来像这样的 xsd(片段):

<xs:complexType name="IDType">
  <xs:choice minOccurs="1" maxOccurs="2">
    <xs:element name="FileID"    minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="IDNumber1" minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="Number"    minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="PNumber"   minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="SS"        minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="Player"    minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="Prior"     minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="BIN"       minOccurs="0" maxOccurs="1" type="an..35" />
    <xs:element name="Mutual"    minOccurs="0" maxOccurs="1" type="an..35" />
  </xs:choice>
</xs:complexType>
<xs:simpleType name="an..35">
  <xs:restriction base="an">
    <xs:maxLength value="35" />
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="an">
   <xs:restriction base="xs:string">
     <xs:pattern value="[ !-~]*" />
   </xs:restriction>
</xs:simpleType>

For some reason this is the Java code that gets generated:

出于某种原因,这是生成的 Java 代码:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "IDType", propOrder = {
    "fileID"
})
public class PatientIDType {
    @XmlElementRefs({
        @XmlElementRef(name = "FileED", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "IDNumber1", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "Number", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "PNumber", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "SS", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "Plaer", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "Prior", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "BIN", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class),
        @XmlElementRef(name = "Mutual", namespace = "http://www.surescripts.com/messaging", type = JAXBElement.class)
    })
    protected List<JAXBElement<String>> fileID;
    /**
     * Gets the value of the fileID property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the fileID property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getFileID().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     */
    public List<JAXBElement<String>> getFileID() {
        if (fileID == null) {
            fileID = new ArrayList<JAXBElement<String>>();
        }
        return this.fileID;
    }

Why is the class generated like this and simply not some kind of string array? I really don't want to have to create JAXBElements every time I want to create something?

为什么类是这样生成的,而不是某种字符串数组?我真的不想每次想创建一些东西时都必须创建 JAXBElements?

How can I have it generate classes for each of the types that simply represent string or something like that?

我怎样才能让它为每种类型生成类,这些类型只代表字符串或类似的东西?

Thanks in advance,

提前致谢,

Ian

伊恩

回答by xcut

This code is generated because your complex type, IDType, contains a choice with a maxOccurrence greater than one, here:

生成此代码是因为您的复杂类型 IDType 包含一个 maxOccurrence 大于 1 的选项,此处:

<xs:choice minOccurs="1" maxOccurs="2">

<xs:choice minOccurs="1" maxOccurs="2">

The contents of this lists are elements with different namesbut the same type. This has no equivalent in standard object-oriented models. JAXB then uses the JAXBElementclass to work around this: a JAXBElementwraps a simple object that contains the data and assigns it a QName.

这个列表的内容是名称不同但类型相同的元素。这在标准的面向对象模型中没有等价物。然后 JAXB 使用JAXBElement该类来解决这个问题:aJAXBElement包装一个包含数据的简单对象并为其分配一个QName.

Thus you can read from this list and write to the list unambiguously by providing:

因此,您可以通过提供以下内容,从该列表中读取并明确写入该列表:

  • The data object (in your case a String since all restrictions from String are represented as a Java String)
  • A JAXBElementwhose getValue()method returns the string
  • 数据对象(在您的情况下是字符串,因为字符串的所有限制都表示为 Java 字符串)
  • AJAXBElementgetValue()方法返回字符串

The JAXB specification contains fairly detailed and reasonably complex explanations of how to deal with repeating choices and repeating sequences. Note that if your sequence contained objects of different types as well as different names, you would end up with List<Object>.

JAXB 规范包含有关如何处理重复选择和重复序列的相当详细且相当复杂的解释。请注意,如果您的序列包含不同类型和不同名称的对象,则最终会得到List<Object>

That was the long explanation, now here are some options:

那是很长的解释,现在这里有一些选择:

  • If you can modify the schema, put a wrapper element around the 8 items, say, "Wrapper". Wrapper will contain a single choice of the elements; Then make IDType contain a sequence of Wrapper elements with minOccurs = 1 and maxOccurs = 2.
  • Create yourself some helper functions to quickly create the JAXBElements. JAXB puts a Factory class in your target package that can help you - for example, it contains references to the Schema namespace, etc.
  • 如果您可以修改架构,请在 8 个项目周围放置一个包装元素,例如“包装”。包装器将包含元素的单一选择;然后让 IDType 包含一个包含 minOccurs = 1 和 maxOccurs = 2 的 Wrapper 元素序列。
  • 创建一些辅助函数来快速创建 JAXBElements。JAXB 在您的目标包中放置了一个可以帮助您的 Factory 类 - 例如,它包含对 Schema 命名空间的引用等。

回答by Ricardo Figueroa

Your ObejctFActory class should have the createMethod for thosr values, somthing like

您的 ObejctFActory 类应该具有 thosr 值的 createMethod,类似

@XmlElementDecl(namespace = "http://www.surescripts.com/messaging", name = "SocialSecurity", scope = PatientIDType.class)
public JAXBElement<String> createPatientIDTypeSocialSecurity(String value) {
    return new JAXBElement<String>(_PayerIDTypeSocialSecurity_QNAME, String.class, PatientIDType.class, value);
}

回答by deverton

If you're using the Sun JAXB implementation, you could try compiling with the xjc:simple mode enabled. See the documentation on simplified bindingfor an example. It should turn

如果您使用的是 Sun JAXB 实现,您可以尝试在启用 xjc:simple 模式的情况下进行编译。有关示例,请参阅有关简化绑定的文档。应该转

public class PatientIDType {
    protected List<JAXBElement<String>> fileID;
}

in to

进入

public class PatientIDType {
    String fileID;
    ...
}

You'll need to compile your schema with a binding customisation file. See Kohsuke's blogfor an example of how to do it.

您需要使用绑定自定义文件编译您的架构。有关如何执行此操作的示例,请参阅Kohsuke 的博客