2013-07-03 68 views
6

有效值我的POJO的对象树表示XML架构。这是用以下jaxb ant脚本创建的。的SAXParseException:值不是“日期”

我想根据模式验证根POJO及其子实体缺少的属性。

我的代码如下:(试行/省略catch块,灵感来自SO质疑How to validate against schema in JAXB 2.0 without marshalling?

public boolean validateAgainstSchema(Pojo pojo) 
{ 
     JAXBContext jc; 
     jc = JAXBContext.newInstance(Pojo.class); 
     SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema = sf.newSchema(new ClassPathResource("schema.xsd").getFile()); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setSchema(schema); 
     marshaller.marshal(schema, new DefaultHandler()); 
     return true; 
} 

我的一个属性(pojo.childEntity.someAttribute)是date

XSD

<xsd:attribute name="some_date" use="required"> 
    <xsd:simpleType> 
    <xsd:restriction base="xsd:date" /> 
    </xsd:simpleType> 
</xsd:attribute> 

的Java

@XmlAttribute(name = "someDate", required = true) 
protected XMLGregorianCalendar someDate; 

它从来自另一POJO(一个是与Hibernate映射)一个java.util.Date对象进行填充。

private static final XMLGregorianCalendar dateToCalendar(Date date) 
{ 
    if (date == null) 
     return null; 
    try 
    { 
     GregorianCalendar c = new GregorianCalendar(); 
     c.setTime(date); 

     return DatatypeFactory.newInstance() 
       .newXMLGregorianCalendar(c); 
    } 
    catch (DatatypeConfigurationException e) 
    { 
     e.printStackTrace(); 
     return null; 
    } 

} 

唯一的例外是:

javax.xml.bind.MarshalException 
- with linked exception: 
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: '2001-05-11T00:00:00.000+02:00' is not a valid value for 'date'.] 

这看起来像JAXB试图设置日期和时间必须只携带日期字段,XMLGregorianCalendard是一个简单的日期时间的容器。

的问题是:是什么原因造成的错误?怎么修?

回答

2

默认情况下为XMLGregorianCalendar属性输出将根据你如何创建它。如果填充时间部分,则时间部分将输出为XML。您可以拨打getXMLSchemaType()方法来查看相应的XML表示是什么:

可以使用@XmlSchemaType注释覆盖表示。

的Java模型(根)

下面是用3个XMLGregorianCalendar字段的对象。 3日我将使用一个@XmlSchemaType批注指定的架构类型。

import javax.xml.bind.annotation.*; 
import javax.xml.datatype.XMLGregorianCalendar; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 

    protected XMLGregorianCalendar default1; 

    protected XMLGregorianCalendar default2; 

    @XmlSchemaType(name="date") 
    protected XMLGregorianCalendar schemaTypeDate; 

} 

演示代码

在演示代码下面我们将创建的XMLGregorianCalendar 2个实例。一个会有架构类型date另一个dateTime。默认情况下,这是编组XML时使用的XML表示。在schemaTypeDate字段中,我们将使用@XmlSchemaType注释来覆盖默认值。

import javax.xml.bind.*; 
import javax.xml.datatype.*; 

public class Demo { 

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

     DatatypeFactory df = DatatypeFactory.newInstance(); 
     XMLGregorianCalendar date = df.newXMLGregorianCalendar("2013-07-03"); 
     XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar("1999-12-31T23:59:00"); 

     Root root = new Root(); 
     root.default1 = date; 
     root.default2 = dateTime; 
     root.schemaTypeDate = dateTime; 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root> 
    <default1>2013-07-03</default1> 
    <default2>1999-12-31T23:59:00</default2> 
    <schemaTypeDate>1999-12-31</schemaTypeDate> 
</root> 

UPDATE

好了,因为我的 XmlGregorianCalendars loooooooooooooooooooooooooooooooooots有没有办法告诉XJC添加 xmlSchemaType属性到所有XGC?

当架构类型是XML Schema类型即xsd:datexsd:dateTime构建的一个,但不是当你扩展了这些类型之一JAXB会为你做这个。

XML架构(schema.xsd)

<?xml version="1.0" encoding="UTF-8"?> 
<schema xmlns="http://www.w3.org/2001/XMLSchema"> 
    <complexType name="root"> 
     <sequence> 
      <element name="dateElement" type="date" /> 
      <element name="dateTimeElement" type="dateTime" /> 
      <element name="extendedDateElement"> 
       <simpleType> 
        <restriction base="date" /> 
       </simpleType> 
      </element> 
     </sequence> 
     <attribute name="dateAttribute" type="date" /> 
     <attribute name="dateTimeAttribute" type="dateTime" /> 
     <attribute name="extendedDateAttribute"> 
      <simpleType> 
       <restriction base="date" /> 
      </simpleType> 
     </attribute> 
    </complexType> 
</schema> 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "root", propOrder = { 
    "dateElement", 
    "dateTimeElement", 
    "extendedDateElement" 
}) 
public class Root { 

    @XmlElement(required = true) 
    @XmlSchemaType(name = "date") 
    protected XMLGregorianCalendar dateElement; 

    @XmlElement(required = true) 
    @XmlSchemaType(name = "dateTime") 
    protected XMLGregorianCalendar dateTimeElement; 

    @XmlElement(required = true) 
    protected XMLGregorianCalendar extendedDateElement; 

    @XmlAttribute(name = "dateAttribute") 
    @XmlSchemaType(name = "date") 
    protected XMLGregorianCalendar dateAttribute; 

    @XmlAttribute(name = "dateTimeAttribute") 
    @XmlSchemaType(name = "dateTime") 
    protected XMLGregorianCalendar dateTimeAttribute; 

    @XmlAttribute(name = "extendedDateAttribute") 
    protected XMLGregorianCalendar extendedDateAttribute; 

} 
+0

事实更复杂(我认为这并不重要):我从日期填充GregCalendar –

+0

@djechelon - 我已经更新了我的答案应该有所帮助的信息。 –

+0

好吧,因为我有XmlGregorianCalendars的loooooooooooooooooooooooooooooooooots有没有办法告诉XJC添加xmlSchemaType属性到所有的XGC? –

0

如果日期是 '2001-05-11T00:00:00.000 + 02:00' 使用

<xsd:restriction base="xsd:dateTime" /> 
+0

对不起。我无法更改架构。它是互操作性过程中使用的标准模式。模式本身*应该是公开的,但我不愿意公开更多关于它的信息 –

相关问题