2012-02-02 227 views
15

的文档required说:minOccurs,nillable和restriction的用途是什么?

如果required()true,那么JavaBean属性被映射到XML模式元素 声明与。 maxOccurs"1"对于单值 财产和"unbounded"为多值财产。

如果required()false,那么Javabean属性映射到XML 模式元素声明minOccurs="0"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。所以,个月要求(必须存在);
  2. 该月有限制。因此,月份只能具有由12个定义的枚举之一定义的值;
  3. nillable的默认值为false。所以,月份不能有空值;
  4. XML模式生成正确。

的问题:

  1. 它接受一个月的abcense(必须不存在);
  2. 它接受月份的任何值,如13(除非不能解析整数);
  3. 它接受空值;

我没有料到这些问题,我错过了什么?
如果该行为是正确的,什么是required目的,nillablexs:restriction

回答

9

Nillable允许空值。例如,如果您有整数或日期,如果它是可删除的,则XML标记可能为空。如果它不是可填充的但不是必需的,那么XML元素要么必须存在于有效内容中,要么根本不存在;一个空标签将无效。

+0

你的意思是的nillable用于定义是否可以为空值时,标签的存在;并且需要用于定义标签是否存在或不存在?在这种情况下,为什么它允许空标签以及为什么它根本不需要标签?我如何注释使minOccurs 1? – falsarella 2012-02-02 13:40:11

+0

minOccurs默认为1。你原来的模式表示那个月是强制性的(标签存在而不是空的)。 – bcody 2012-02-02 14:32:09

+0

那么为什么它接受月份的abcense或空值?它不会在响应中产生错误! – falsarella 2012-02-02 15:00:51

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(); 
    } 

} 

UPDATE

的JAXB RI通常引发严重程度1转换问题的ValidationEvent。默认ValidationEventHandler忽略严重性小于2的所有问题。这通常会导致将值设置为空。您可以覆盖ValidationEventHandler如下:

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

然而,JAXB RI不会出现丢有关转换枚举值(可能的错误)的事件。如果你碰巧使用的EclipseLink JAXB(莫西)为您的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) 

更多信息

+0

如果需要month,那么为什么它接受null或month的缺席(0次出现)? – falsarella 2012-02-02 16:06:42

+0

关于如何生成模式..我对这一代的了解是,它在这里是自动的。在JBoss启动时,给定web.xml映射,WebService和XmlXXX注释,就可以创建它。 顺便说一句,我想这不是重点,我的xsd正在正确生成。但是,例如,它接受13作为该月的输入(解组为null)。此外,它接受null,它是缺席。为什么?创建枚举限制而不创建会给我同样的接受行为。 – falsarella 2012-02-02 16:40:11

+0

我发现我可以创建一个afterUnmarshal方法来处理null的,例如,它可以工作,但是如果它接受0的出现以及创建限制的目的是什么(使用枚举),在xsd中使用minOccurs 1的东西的目的是什么?如果输入值在“范围”内没有验证? – falsarella 2012-02-02 16:42:45

4

的目的requiredminOccurs不会误导,问题是架构验证未启用。只是使SchemaValidationWebService定义XmlType的映射的顺序如下:

Web服务:

@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; 

    //... 
} 
1

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

我认为这是最好的。验证消耗资源和时间。对于大多数Web服务,我们需要的所有WSDL都是为客户提供能够与WebService交谈的定义,而不是像属性是否为null那样设置限制。

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

1

我看了一下你发布的XSD结构 - 并发现你没有使用你为本月定义的复杂类型,Insteqad在Java代码中处理它,你可以在XSD中提及所有的类型, minOccur月 - 复杂类型中的元素丢失。请使用任何standered XSD到Java发生器,它会做所有的java文件生成任务,为您

The convention are as follow - 

MinOccur = 0 --> the element can be abscent in input , and can be present 

MinOccur = 1 --> the element must be there in input 
(but if you use it, then your java generated member will be of list type - list of ENUM for Int) 

If you don't write MinOccur in attributes - then it makes the element mandatory , (then you java generated member will be of simply ENUM for int) 


MaxOccur = 1 --> minimum one element can be there in input 
(but if you use it, then your java generated member will be of list type - list of ENUM for Int) 


MaxOccur = unbound --> only one element can be there in input 
(if you use it, then your java generated member will be of list type - list of ENUM for Int) 

    <xs:complexType name="wsData"> 
    <xs:sequence> 
    <xs:element name="month" type="xmlMonthType" minOccurs="1" nillable="false" /> 
    <xs:element name="userLogin" type="xs:string" minOccurs="0" /> 
    </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>