SAXParseException: value is not a valid value for 'date'

19,285

Solution 1

By default the output for an XMLGregorianCalendar property will be based on how you create it. If you populate the time portion, then the time portion will be output to XML. You can call the getXMLSchemaType() method to see what the corresponding XML representation is:

You can use the @XmlSchemaType annotation to override the representation.

Java Model (Root)

Below is an object with 3 XMLGregorianCalendar fields. On the 3rd I will use an @XmlSchemaType annotation to specify the schema type.

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

In the demo code below we will create 2 instances of XMLGregorianCalendar. One will have schema type date the other dateTime. By default this is the XML representation used when marshalling to XML. On the schemaTypeDate field we will use the @XmlSchemaType annotation to override the default.

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

}

Output

<?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, since I have loooooooooooooooooooooooooooooooooots of XmlGregorianCalendars is there a way to tell XJC to add the xmlSchemaType attribute to all XGCs?

JAXB will do this for you when the schema type is one of the build in XML Schema types i.e. xsd:date or xsd:dateTime, but not when you have extended one of these types.

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;

}

Solution 2

If the date is '2001-05-11T00:00:00.000+02:00' use

<xsd:restriction base="xsd:dateTime" />
Share:
19,285

Related videos on Youtube

usr-local-ΕΨΗΕΛΩΝ
Author by

usr-local-ΕΨΗΕΛΩΝ

Chuck Norris is the only one who can type my name on a keyboard by using my teeth as keys, courtesy of a roundhouse kick in my mouth

Updated on June 04, 2022

Comments

  • usr-local-ΕΨΗΕΛΩΝ
    usr-local-ΕΨΗΕΛΩΝ almost 2 years

    I have an object tree of POJOs that represents an XML Schema. This was created with the following jaxb ant script.

    I want to validate the root POJO and its children entities against the schema for missing attributes.

    My code is the following: (try/catch block omitted, inspired by SO question 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;
    }
    

    One of my attributes (pojo.childEntity.someAttribute) is a 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;
    

    It gets populate from a java.util.Date object from another POJO (one that is mapped with Hibernate).

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

    The exception is:

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

    This looks like JAXB tries to set both date and time for a field that must carry only the date, and XMLGregorianCalendard is simply a datetime container.

    The question is: what causes the error? How to fix?

  • usr-local-ΕΨΗΕΛΩΝ
    usr-local-ΕΨΗΕΛΩΝ almost 11 years
    Sorry. I cannot change the schema. It is a standard schema used in an interoperability process. The schema itself should be public but I prefer not disclosing more information about it
  • usr-local-ΕΨΗΕΛΩΝ
    usr-local-ΕΨΗΕΛΩΝ almost 11 years
    The truth is more complex (I thought it didn't matter): I populate the GregCalendar from a Date
  • bdoughan
    bdoughan almost 11 years
    @djechelon - I have updated my answer with information that should help.
  • usr-local-ΕΨΗΕΛΩΝ
    usr-local-ΕΨΗΕΛΩΝ almost 11 years
    Ok, since I have loooooooooooooooooooooooooooooooooots of XmlGregorianCalendars is there a way to tell XJC to add the xmlSchemaType attribute to all XGCs?
  • bdoughan
    bdoughan almost 11 years
    @djechelon - The @XmlSchemaType annotations should have already been added for you (were they?). Which implementation and version of JAXB are you using? If you are using the JAXB in the JDK, which version of the JDK are you using?
  • usr-local-ΕΨΗΕΛΩΝ
    usr-local-ΕΨΗΕΛΩΝ almost 11 years
    Actually I found that my root entity was annotated, but a child of it (throwing the error) was not. I'm looking to confirm whether the XSD is really public so at least I will be able to link it.