当Xml不包含标记时,JAXB返回null

时间:2014-08-22 01:34:52

标签: java xml jaxb

我遇到了JAXB和Unmarshalling以下XML的问题

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

我获得了模式并使用JAXB xjc工具生成了以下属性定义:

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

}

正如您所看到的,发送XML的设备不包含ID1标记,它只是将ID1数据添加为根标记的值。当解组此Xml时,对getID1的任何调用都返回null。我很困惑用什么注释来改变类以支持根标记中的数据分配给id1字段。

关于注释更改的任何想法都会使这项工作成功吗?

3 个答案:

答案 0 :(得分:2)

您的ID类应该是......

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

}

我用这个主要的方法尝试了这个bean ...

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

输出生成为..

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

我希望我已经向你提供了有关你问题的所有答案。

答案 1 :(得分:2)

为什么你会空无一人

您正在解组的XML与您从中生成对象模型的XML架构不匹配。

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

问题

当元素同时具有文本和元素时,据说它具有混合内容。您的XML架构目前不会考虑到这一点。

解决方案

将与ID元素对应的复杂类型的定义更改为mixed="true"。然后重新生成JAXB模型。

为什么你不喜欢解决方案

由于混合内容的类型分散在子元素中,因此您将获得一个非常不同的JAXB模型。基本上ID的类将包含一个包含所有内容的List属性。这对于找到XML格式是必要的。

答案 2 :(得分:2)

这是XML的正确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>

令人遗憾的结果是生成的类IdType包含

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

用于包含ID文本子(children!)和所有ID元素子项。因此,ID的处理可能类似于:

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