minOccurs,nillable和限制的目的是什么?

时间:2012-02-02 12:00:26

标签: java xml jaxb wsdl xsd

required 的文档说:

  

如果是required()   true,然后将Javabean属性映射到XML架构元素   声明minOccurs="1"。对于单个值,maxOccurs"1"   属性和"unbounded"表示多值属性。

     

如果required()false,则Javabean属性将映射到XML   带minOccurs="0"的模式元素声明。对于a,maxOccurs"1"   单值属性,"unbounded"表示多值属性。

nillable 的文档说:

  

如果nillable()true,则JavaBean属性将映射到XML   架构nillable元素声明。

<小时/> xs:complexType的代码:

public class WSData {
    //...

    @XmlElement(required = true, nillable = false)
    public void setMonth(XmlMonthType month) {
        this.month = month;
    }

    public void setUserLogin(String userLogin) {
        this.userLogin = userLogin;
    }
}

xs:simpleType的代码:

@XmlType
@XmlEnum(Integer.class)
public enum XmlMonthType {
    @XmlEnumValue("1")
    JANUARY,
    @XmlEnumValue("2")
    FEBRUARY,
    @XmlEnumValue("3")
    MARCH,
    /* ... months 4 ~9 ... */
    @XmlEnumValue("10")
    OCTOBER,
    @XmlEnumValue("11")
    NOVEMBER,
    @XmlEnumValue("12")
    DECEMBER;
}

生成的XML架构:

<xs:complexType name="wsData">
  <xs:sequence>
    <xs:element name="month" type="xs:string"/>
    <xs:element minOccurs="0" name="userLogin" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

<xs:simpleType name="xmlMonthType">
  <xs:restriction base="xs:int">
    <xs:enumeration value="1"/>
    <xs:enumeration value="2"/>
    <xs:enumeration value="3"/>
    <!-- ... months 4 ~9 ... -->
    <xs:enumeration value="10"/>
    <xs:enumeration value="11"/>
    <xs:enumeration value="12"/>
  </xs:restriction>
</xs:simpleType>

<小时/> 事实:

  1. minOccurs 的默认值为1.因此, month 是必需的(必须存在);
  2. 月份有限制。因此, month 只能有一个由12个定义的枚举中的一个定义的值;
  3. nillable 的默认值为false。因此,不能有空值;
  4. 正确生成XML Schema。
  5. 问题:

    1. 接受月份的贬值(必须不存在);
    2. 它接受月份的任何值,如13(除非不能解析为Integer);
    3. 接受空值;
    4. 我没想到会遇到这些问题,我错过了什么吗? 如果该行为正确, required nillable xs:restriction 的目的是什么?

5 个答案:

答案 0 :(得分:9)

Nillable允许空值。例如,如果您有一个Integer或Date,如果它是可为空的,则XML标记可能为空。如果它不是可存档但不是必需的,那么XML元素要么必须存在有效​​内容,要么根本不存在;空标签无效。

答案 1 :(得分:5)

  

将minOccurs 1设为需要月份;

minOccurs的默认值为1,因此需要month元素。请注意,必须将minOccurs="0"添加到userLogin以使其成为可选项。

<xs:complexType name="wsData">
  <xs:sequence>
    <xs:element name="month" type="xs:string"/>
    <xs:element minOccurs="0" name="userLogin" type="xs:string"/>
  </xs:sequence>
</xs:complexType>
  

使用生成的限制验证月份(没有XmlAdapter)。

您可以在Unmarshaller上设置Schema的实例以验证输入:

<强>演示

以下代码可用于生成XML架构:

package forum9111936;

import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(WSData.class);
        SchemaOutputResolver sor = new SchemaOutputResolver() {

            @Override
            public Result createOutput(String namespaceUri,
                    String suggestedFileName) throws IOException {
                StreamResult result = new StreamResult(System.out);
                result.setSystemId(suggestedFileName);
                return result;
            }

        };
        jc.generateSchema(sor);
        System.out.println();
    }

}

<强>更新

JAXB RI通常会针对转换问题抛出ValidationEvent的严重性1。默认ValidationEventHandler忽略严重性小于2的所有问题。这通常会导致值设置为null。您可以按如下方式覆盖ValidationEventHandler

    unmarshaller.setEventHandler(new ValidationEventHandler() {
        @Override
        public boolean handleEvent(ValidationEvent event) {
            System.out.println(event);
            return event.getSeverity() < ValidationEvent.ERROR;
        }
    });

然而,JAXB RI似乎不会抛出与转换枚举值相关的事件(可能的错误)。如果您恰好使用EclipseLink JAXB(MOXy)作为JAXB提供程序,那么您将获得如下异常:

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-116] (Eclipse Persistence Services - 2.4.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: No conversion value provided for the value [13] in field [month/text()].
Mapping: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[month-->month/text()]
Descriptor: XMLDescriptor(forum9111936.WSData --> [])
    at org.eclipse.persistence.exceptions.DescriptorException.noFieldValueConversionToAttributeValueProvided(DescriptorException.java:1052)
    at org.eclipse.persistence.mappings.converters.ObjectTypeConverter.convertDataValueToObjectValue(ObjectTypeConverter.java:140)
    at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:287)
    at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:190)
    at org.eclipse.persistence.oxm.record.UnmarshalRecord.endElement(UnmarshalRecord.java:910)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:133)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:83)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:72)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:838)
    at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:626)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:472)
    at forum9111936.Demo2.main(Demo2.java:30)

了解更多信息

答案 2 :(得分:4)

requiredminOccurs的目的不是误导,问题是未启用架构验证。只需启用 SchemaValidation 即可 WebService 定义 > XmlType 的映射如下:

网络服务:

@javax.jws.WebService
@org.jboss.ws.annotation.SchemaValidation(enabled = true)
public class WebServiceClass {

    @javax.jws.WebMethod
    public WSResponseData webServiceMethod() {
        //...
    }
}

XmlType将:

@javax.xml.bind.annotation.XmlType(propOrder = {"field1", "field2", "field3"})
public class WSData {
    //...

    private String field1;

    private Long field2;

    private XmlMonthType field3;

    //...
}

答案 3 :(得分:1)

事实上,似乎SOAP信封在WSDL上未经过验证,无论是在服务器上还是在客户端上。

我觉得这样做最好。验证会消耗资源和时间。对于大多数WebServices,WSDL所需要的只是向客户端提供能够与WebService通信的定义,而不是设置限制,例如属性是否可以为null。

当服务器和客户端在同一台PC上时,与内部呼叫相比,Axis2增加了3-5百万的开销。不必要的验证只会增加开销。我最好让操作抛出异常并手动验证真正需要的东西。

答案 4 :(得分:1)

我查看了你发布的XSD结构 - 并发现你没有使用你已经定义的月份的复杂类型,Insteqad在java代码上处理它你可以在XSD中提到所有这些,以及minOccur on month - 缺少复杂类型中的元素。请使用任何standered XSD到java生成器,它将为您完成所有java文件生成任务

onLoad