如何使用JAXB从Java中获取XSD的minOccurs / maxOccurs值?

时间:2014-02-21 08:31:12

标签: java jaxb xsd maven-jaxb2-plugin

我的应用程序正在调用webservice,我已经使用maven-jaxb2-plugin从WSDL / XSD生成了Java类。 webservice调用工作正常一段时间,但最近我在将对象编组为XML时遇到了问题:

[org.xml.sax.SAXParseException: cvc-complex-type.2.4.d: Invalid content was found starting with element 'ns1:TheFooAndBarThing'. 
No child element '{"http://www.myschemanamespace.xyz/v1":BarId}' is expected at this point.]

XSD部分如下所示:

<xs:complexType name="TheFooAndBarThing">
    <xs:sequence>
        <xs:element name="FooId" minOccurs="1" maxOccurs="1" type="nx:FooIdType"/>
        <xs:element name="BarId" minOccurs="1" maxOccurs="100" type="nx:BarIdType"/>
    </xs:sequence>
</xs:complexType>

生成的类TheFooAndBarThing看起来像这样(删除了Javadoc):

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "TheFooAndBarThing", propOrder = {
    "fooId",
    "barId"
})
public class TheFooAndBarThing {

    @XmlElement(name = "FooId", required = true)
    protected String fooId;
    @XmlElement(name = "BarId", required = true)
    protected List<String> barId;

    public String getFooId() {
        return fooId;
    }

    public void setFooId(String value) {
        this.fooId = value;
    }

    public List<String> getBarId() {
        if (barId == null) {
            barId = new ArrayList<String>();
        }
        return this.barId;
    }

}

我花了一些时间和咖啡来找出真正的问题。我的错误是我在列表中放了100多个BarId个元素。

所以这是我的问题:
如何从XSD获取maxOccurs / minOccurs值到我的Java代码中,以便在构建元素列表时将其用作最大/最小值?

2 个答案:

答案 0 :(得分:3)

简短的回答:没有简单的方法。

模式派生类不再引用原始模式。即使您使用XSOM或其他东西来解析原始模式,您也无法找到相应的XML Schema结构来进行检查。

解决问题的最佳方法是撰写自定义XJC plugin(我写了quite a few of them)。

当XJC编译schmema时,它首先创建一个模型,然后是所谓的轮廓(预渲染代码),然后渲染代码。该模型仍然包含有关原始XML Schema结构的信息,因此您可以在那里找到所有相关的min / maxOccurs信息。

问题在于,您不必总是在架构构造和架构派生类的属性之间进行1:1映射。有时几个元素映射到一个属性。有大量例外和特殊情况。不过,你可以让它适用于直截了当的案例。无论如何,这项任务并不容易。

答案 1 :(得分:1)

使用可以尝试JAXB-Facets

以下是为 minoccurs maxoccurs 设置特定值的示例:

@MinOccurs(value = 0)
@MaxOccurs(value = 100)
private List<String> test;