2013-07-03 21 views
6

Ho un albero di oggetti di POJO che rappresenta uno schema XML. Questo è stato creato con il seguente script ant jaxb.SAXParseException: value non è un valore valido per 'date'

voglio convalidare il POJO radice e dei suoi bambini entità contro lo schema per gli attributi mancanti.

Il mio codice è il seguente: (provate/blocco catch omesso, ispirato domanda 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; 
} 

Uno dei miei attributi (pojo.childEntity.someAttribute) è un 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; 

Viene popolato da un oggetto java.util.Date da un altro POJO (uno mappato con Ibernazione).

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

} 

L'eccezione è:

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'.] 

Questo appare come JAXB cerca di impostare sia la data e l'ora per un campo che deve portare solo la data, e XMLGregorianCalendard è semplicemente un contenitore datetime.

La domanda è: cosa causa l'errore? Come risolvere?

risposta

2

Per impostazione predefinita l'uscita per una proprietà XMLGregorianCalendar si baserà su come lo si crea. Se si popola la porzione di tempo, la parte relativa al tempo verrà inviata a XML. È possibile chiamare il metodo getXMLSchemaType() per vedere che cosa la rappresentazione XML corrispondente è:

È possibile utilizzare il @XmlSchemaType annotazioni per ignorare la rappresentazione.

Java Model (Root)

Di seguito è un oggetto con 3 XMLGregorianCalendar campi. Il 3 userò un'annotazione @XmlSchemaType per specificare il tipo di schema.

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; 

} 

Demo Codice

Nel codice demo di seguito creeremo 2 istanze di XMLGregorianCalendar. Uno avrà schema tipo date l'altro dateTime. Per impostazione predefinita, questa è la rappresentazione XML utilizzata durante il marshalling in XML. Nel campo useremo l'annotazione @XmlSchemaType per sovrascrivere il valore predefinito.

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

} 

uscita

<?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

Ok, dal momento che ho loooooooooooooooooooooooooooooooooots di XmlGregorianCalendars c'è un modo per dire XJC per aggiungere il 012.351.641.061.attributo xmlSchemaType su tutti gli XGC?

JAXB farà questo per voi quando il tipo di schema è uno dei la configurazione in tipi di schema XML cioè xsd:date o xsd:dateTime, ma non quando si hanno esteso uno di questi tipi.

XML Schema (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> 

Root

@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

La verità è più complessa (pensavo che non fosse importante): popolo GregCalendar da una data –

+0

@djechelon - Ho aggiornato la mia risposta con informazioni che dovrebbero aiutare. –

+0

Ok, dato che ho loooooooooooooooooooooooooooooooooots di XmlGregorianCalendars c'è un modo per dire a XJC di aggiungere l'attributo xmlSchemaType a tutti gli XGC? –

0

Se la data è '2001-05-11T00: 00: 00.000 + 02: 00' usare

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

spiacenti. Non riesco a cambiare lo schema. È uno schema standard utilizzato in un processo di interoperabilità. Lo schema stesso * dovrebbe * essere pubblico ma preferisco non rivelare ulteriori informazioni a riguardo –