2013-07-03 32 views
6

Mam drzewo obiektów POJO, które reprezentuje schemat XML. Zostało to utworzone przy użyciu następującego skryptu mrówkowego: jaxb.SAXParseException: wartość nie jest poprawną wartością dla 'date'

Chcę, aby sprawdzić poprawność Pojo korzeń i jego dzieci podmioty wobec schematu dla brakujących atrybutów.

Mój kod jest następujący: (spróbuj/bloku catch pominięty, zainspirowany SO pytanie 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; 
} 

jeden z moich atrybutów (pojo.childEntity.someAttribute) jest 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; 

Zostanie wypełniony z obiektu java.util.Date z innego obiektu POJO (odwzorowanego za pomocą Hibernuj).

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

} 

Wyjątkiem jest:

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

To wygląda JAXB próbuje ustawić zarówno datę i czas na polu, które muszą jedynie datę i XMLGregorianCalendard to po prostu pojemnik datetime.

Pytanie brzmi: co powoduje błąd? Jak naprawić?

Odpowiedz

2

Domyślnie wyjście dla własności XMLGregorianCalendar będzie opierać się na jak go utworzyć. Jeśli zapełnisz część czasu, część czasu zostanie wyprowadzona do XML. Można wywołać metodę getXMLSchemaType() aby zobaczyć, co odpowiada reprezentacji XML jest:

Można użyć @XmlSchemaType adnotacji zastąpić reprezentację.

Java model (korzeń)

Poniżej jest obiektem z 3 XMLGregorianCalendar dziedzinach. 3 dnia użyję adnotacji @XmlSchemaType, aby określić typ schematu.

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; 

} 

Code Demo

W kodzie demo poniżej będziemy utworzyć 2 instancje XMLGregorianCalendar. Jeden będzie miał schemat typu date drugi dateTime. Domyślnie jest to reprezentacja XML używana podczas sortowania do XML. Na polu schemaTypeDate użyjemy adnotacji @XmlSchemaType, aby zastąpić domyślną.

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

} 

Wyjście

<?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, ponieważ mam loooooooooooooooooooooooooooooooooots z XmlGregorianCalendars czy istnieje sposób, aby powiedzieć XJC dodać Atrybut xmlSchemaType dla wszystkich XGC?

JAXB zrobi to za ciebie, gdy typ schematu jest jednym z typów kompilacji w XML Schema tj xsd:date lub xsd:dateTime, ale nie wtedy, gdy masz przedłużony jeden z tych typów.

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> 

głównej

@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

Prawda jest bardziej złożona (myślałem, że to nie ma znaczenia): zapełniam gregCalendar od daty –

+0

@djechelon - zaktualizowałem swoją odpowiedź informacje, które powinny pomóc. –

+0

OK, ponieważ mam loooooooooooooooooooooooooooooooooots XmlGregorianCalendars czy jest jakiś sposób, aby powiedzieć XJC, aby dodał atrybut xmlSchemaType do wszystkich XGC? –

0

Jeśli data jest '2001-05-11T00: 00: 00.000 + 02: 00' używać

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

Niestety. Nie mogę zmienić schematu. Jest to standardowy schemat używany w procesie współdziałania. Sam schemat * powinien * być jawny, ale wolę nie ujawniać więcej informacji na jego temat. –