2013-07-03 27 views
6

ich einen Objektbaum von POJOs, die ein XML-Schema darstellt. Dies wurde mit dem folgende jaxb Ant-Skript erstellt.SAXParseException: Wert ist kein gültiger Wert für ‚date‘

Ich möchte für fehlende Attribute die Wurzel POJO und seine Kinder Einheiten gegen das Schema validieren.

Mein Code ist folgende: (versuchen Sie/weggelassen catch-Block, inspiriert von SO How to validate against schema in JAXB 2.0 without marshalling? Frage)

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

Einer meiner Attribute (pojo.childEntity.someAttribute) ein 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; 

Es wird von einem java.util.Date Objekt aus einer anderen POJO (eine, die mit Hibernate abgebildet wird) füllen.

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

} 

Die Ausnahme ist:

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

Das sieht aus wie JAXB sowohl Datum und Zeit für ein Feld zu setzen versucht, die nur das Datum tragen muss, und XMLGregorianCalendard ist einfach ein Datetime-Container.

Die Frage ist: was den Fehler verursacht? Wie repariert man?

Antwort

2

Standardmäßig verwenden die Ausgabe für eine XMLGregorianCalendar Eigenschaft wird auf der Grundlage, wie Sie es schaffen. Wenn Sie den Zeitabschnitt auffüllen, wird der Zeitabschnitt in XML ausgegeben. Sie können die getXMLSchemaType() Methode aufrufen, um zu sehen, was die entsprechende XML-Darstellung ist:

Sie verwenden, um die @XmlSchemaType Annotation die Darstellung außer Kraft zu setzen.

Java Model (Root)

Im Folgenden finden Sie ein Objekt mit 3 XMLGregorianCalendar Feldern. Am 3. werde ich eine @XmlSchemaType Anmerkung verwenden, um den Schematyp angeben.

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

Im Demo-Code unten wir zwei Instanzen von XMLGregorianCalendar schaffen. Einer wird Schematyp date der andere dateTime haben. Standardmäßig ist dies die XML-Darstellung, die beim Marshalling nach XML verwendet wird. Im Feld schemaTypeDate verwenden wir die Annotation @XmlSchemaType, um den Standardwert zu überschreiben.

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

} 

Ausgabe

<?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, da ich loooooooooooooooooooooooooooooooooots von XmlGregorianCalendars haben, ist es eine Möglichkeit, XJC zu sagen, diehinzufügenxmlSchemaType-Attribut für alle XGCs?

JAXB wird dies für Sie tut, wenn der Schematyp eines des Build in XML-Schema-Typ ist das heißt xsd:date oder xsd:dateTime, aber nicht, wenn Sie einer dieses Typ erweitert.

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> 

Wurzel

@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

Die Wahrheit ist komplexer (ich dachte, es wäre egal): Ich bevölkere den GregCalendar von einem Datum –

+0

@djechelon - Ich habe meine Antwort mit aktualisiert Informationen, die helfen sollten. –

+0

Ok, da ich looooooooooooooooooooooooooooooooots von XmlGregorianCalendars habe, gibt es eine Möglichkeit, XJC mitzuteilen, dass das xmlSchemaType-Attribut allen XGCs hinzugefügt werden soll? –

0

Wenn das Datum '2001-05-11T00: 00: 00.000 + 02: 00'

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

Es tut uns leid. Ich kann das Schema nicht ändern. Es ist ein Standardschema, das in einem Interoperabilitätsprozess verwendet wird. Das Schema selbst * sollte * öffentlich sein, aber ich ziehe es vor, keine weiteren Informationen darüber zu veröffentlichen –

Verwandte Themen