...">

JAXB returns null when Xml contains no tag

I am having a problem with JAXB and Unmarshalling the following XML

<ns2:ID entry-method="manual"> 123456789012345678
    <ns2:ID2>123456789012345678</ns2:ID2>
</ns2:ID>

      

I got the schema and using the xjc JAXB tool, it generated the following property definition:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "ID1",
    "ID2",
    "ID3"
})
@XmlRootElement(name = "ID")
public class ID {

@XmlElement(name = "ID1")
protected String id1;
@XmlElement(name = "ID2")
protected String id2;
@XmlElement(name = "ID3")
protected String id3;
@XmlAttribute(name = "entryMethod")
protected String entryMethod;

public String getId1() {
     return id1
}

public void setId1(String value) {
    this.id1 = value;

}

public String getId2() {
    return id2

}

public void setId2(String value) {
    this.id2 = value;
}

public String getId3() {
    return id3;
}

public void setId3(String value) {
    this.id3 = value;
}

public String getEntryMethod() {
    if (entryMethod == null) {
        return "swipe";
    } else {
        return entryMethod;
    }
}

public void setEntryMethod(String value) {
    this.entryMethod = value;
}

      

}

As you can see, the device that is sending the XML does not include the ID1 tag, it just adds the ID1 data as the root tag value. When Unmarshalling this Xml, any calls to getID1 will return null. I am confused about what annotations to use to modify the class to support the data in the root tag to be assigned in the id1 field.

Any ideas on what changes to the annotation would make this work?

  • Tim
+3


source to share


3 answers


This is the correct XML schema content (excluding namespace) for your XML:

<xs:element name="ID" type="IdType"/>

<xs:complexType name="IdType" mixed="true">
  <xs:sequence>
    <xs:element name="id2" type="xs:string"/>
    <xs:element name="id3" type="xs:string"/>
  </xs:sequence>
  <xs:attribute name="entry-method" type="xs:string"/>
</xs:complexType>

      

The sad consequence is that the generated IdType class contains



public List<Serializable> getContent() {
    if (content == null) {
        content = new ArrayList<Serializable>();
    }
    return this.content;
}

      

to contain the ID text child (children!) and all child ID elements. So the handling of the identifier could be something like this:

JAXBElement<IdType> jbe =
        (JAXBElement<IdType>)u.unmarshal( new File( "mixed.xml" ) );
for( Object obj: jbe.getValue().getContent() ){
    System.out.println( obj.getClass() + " " + obj );
    if( obj instanceof String ){
        // text child (even the blank space
    } else if( obj instanceof JAXBElement ){
        // process an element child wrapped into JAXBElement
    }
}

      

+2


source


Your ID class should be ...

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "content"
})
@XmlRootElement(name = "ID")
public class ID {

    @XmlElementRefs({
        @XmlElementRef(name = "ID3", type = JAXBElement.class),
        @XmlElementRef(name = "ID2", type = JAXBElement.class),
        @XmlElementRef(name = "ID1", type = JAXBElement.class)
    })
    @XmlMixed
    protected List<Serializable> content;
    @XmlAttribute(name = "entry-method")
    protected String entryMethod;

    /**
     * Gets the value of the content property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the content property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getContent().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link String }
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * 
     * 
     */
    public List<Serializable> getContent() {
        if (content == null) {
            content = new ArrayList<Serializable>();
        }
        return this.content;
    }

    /**
     * Gets the value of the entryMethod property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getEntryMethod() {
        return entryMethod;
    }

    /**
     * Sets the value of the entryMethod property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setEntryMethod(String value) {
        this.entryMethod = value;
    }

}

      

I tried this bean with this main method ...

public static void main(String[] args) throws JAXBException {
   final JAXBContext context = JAXBContext.newInstance(ID.class);

    final Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

    final ID id = new ID();
    id.setEntryMethod("method");

    ObjectFactory o = new ObjectFactory();

    id.getContent().add("sample text");
    id.getContent().add(o.createIDID1("id1"));

    m.marshal(id, System.out);
}

      



The output is generated ..

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ID entry-method="method">sample text
    <ID1>id1</ID1>
</ID>

      

Hope I gave you all the answers to your question.

+2


source


Why are you getting zero

The XML you are unmounting does not match the XML schema you generated the object model from.

<ns2:ID entry-method="manual"> 123456789012345678
    <ns2:ID2>123456789012345678</ns2:ID2>
</ns2:ID>

      

Problem

When an element has both text and an element, it has mixed content. Your XML schema does not currently account for this.

Decision

Modify the definition of the complex type corresponding to the element ID

to have mixed="true"

. Then rebuild the JAXB model.

Why won't you like the solution

Since the type has mixed content scattered among the children, you end up with a very different JAXB model. Essentially, the class for ID

will have one property List

that contains all the content. This is required for XML trip searches.

+2


source







All Articles