views:

130

answers:

2

I am using an xsd having two <xs:list/> elements.

<xs:element name="packorder1" type="DateTimeTypeXsList"/>
<xs:element name="packorder2" type="DateTypeXsList"/>
<xs:simpleType name="DateTimeTypeXsList">
    <xs:list itemType="xs:dateTime"/>
</xs:simpleType>
<xs:simpleType name="DateTypeXsList">
    <xs:list itemType="xs:date"/>
</xs:simpleType>

For these elements the JAXB generated code is :

@XmlList
@XmlElement(required = true)
protected List<XMLGregorianCalendar> packorder1;

@XmlList
@XmlElement(required = true)
protected List<XMLGregorianCalendar> packorder2;

The generated code does not contain any information about which one of these element is of date type and which one is of type dateTime.Now if i try to create an xml using jaxbcontext of this class it will create a dateTime element for both packorder1 and packorder2 which it should not do. So how can i distinguish between these two elements?

A: 

I'm not sure if I'm misunderstanding you, but XJC should generate fields of type XmlGregorianCalendar for both dateTime and date schema types. It is up to you to know which is which; it's no different to xs:string and xs:NMTOKEN both mapping to java.lang.String.

skaffman
yes you are right it is generating XMLGregorianCalendar for both these elements.Actually i am also generating xml using JAXBContext of this class. I am getting dateTime default value for both date and dateTime xs:list elements.I guess the problem is because of the missing @XmlSchemaType(name = "date") annotation in case of xs:list. How can i fix this? Do we have any such JAXB binding?
harry
@harry: Please edit your question and add specific examples of what you're seeing, and what you think it should be doing.
skaffman
@skaffman Please check the question now and let me know if you need further clarification.
harry
A: 

You can add an @XmlSchemaType annotation to your model to control the output

        @XmlList 
        @XmlElement(required = true) 
        @XmlSchemaType(name="dateTime")
        protected List<XMLGregorianCalendar> packorder1; 

        @XmlList 
        @XmlElement(required = true) 
        @XmlSchemaType(name="date")
        protected List<XMLGregorianCalendar> packorder2;

Also, XMLGregorianCalendar knows what XML schema type corresponds to the data its holding, see the getXMLSchemaType method on XMLGregorianCalendar:

http://java.sun.com/javase/6/docs/api/javax/xml/datatype/XMLGregorianCalendar.html#getXMLSchemaType()

JAXB will then use that schema type to marshal the document:

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlList;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.datatype.XMLGregorianCalendar;

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

        public Root() {
            packorder1 = new ArrayList<XMLGregorianCalendar>();
            packorder2 = new ArrayList<XMLGregorianCalendar>();
        }


        @XmlList 
        @XmlElement(required = true) 
        protected List<XMLGregorianCalendar> packorder1; 

        @XmlList 
        @XmlElement(required = true) 
        protected List<XMLGregorianCalendar> packorder2;

        public List<XMLGregorianCalendar> getPackorder1() {
            return packorder1;
        }

        public void setPackorder1(List<XMLGregorianCalendar> packorder1) {
            this.packorder1 = packorder1;
        }

        public List<XMLGregorianCalendar> getPackorder2() {
            return packorder2;
        }

        public void setPackorder2(List<XMLGregorianCalendar> packorder2) {
            this.packorder2 = packorder2;
        } 

    }

and

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class Demo {

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

        Root root = new Root();
        DatatypeFactory df = DatatypeFactory.newInstance();

        XMLGregorianCalendar dateTime1 = df.newXMLGregorianCalendar("2010-07-27T12:34:56");
        root.getPackorder1().add(dateTime1);

        XMLGregorianCalendar dateTime2 = df.newXMLGregorianCalendar("2010-03-17T01:02:03");
        root.getPackorder1().add(dateTime2);

        XMLGregorianCalendar date1 = df.newXMLGregorianCalendar("2010-07-27");
        root.getPackorder2().add(date1);

        XMLGregorianCalendar date2 = df.newXMLGregorianCalendar("2010-03-17");
        root.getPackorder2().add(date2);

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

}

will produce:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <packorder1>2010-07-27T12:34:56 2010-03-17T01:02:03</packorder1>
    <packorder2>2010-07-27 2010-03-17</packorder2>
</root>
Blaise Doughan
Hi Blaise Thanks for the input. But my main problem is that I dont want to change the JaxB generated classes manually. For normal Date and DateTime; the generated JaxB classes has the annotation @XmlSchemaType(name="dateTime") or @XmlSchemaType(name="date") properly. But for same DataType in xs:list no annotations are generated. I am looking for any solutions like a binding that will generate this annotation even for xs:list
harry