@XmlElement有多个名字

时间:2014-07-03 13:18:41

标签: java xml xml-parsing jaxb

我遇到这种情况,试图充当两个API之间的网关。我需要做的是:

  1. 向APIa提出请求;
  2. 将XML响应解析(编组)到java对象中;
  3. 对它做一点改动;
  4. 然后以XML(unmarshal)向另一端(APIb)发出响应。
  5. 问题是我使用相同的对象来解析API响应并将响应发送到另一端。

    public class ResponseAPI{
    
    @XmlElement(name="ResponseCode") //I receive <ResponseCode> but I need to send <ResultCode>
    private String responseCode;
    
    //getter and setter
    }
    

    正如评论所说:我收到但我需要发送

    有没有办法在不必创建另一个带有ResultCode的额外类的情况下完成这项工作?

    提前感谢!

2 个答案:

答案 0 :(得分:3)

您可以使用@XmlElements注释

尝试下一个解决方案
@XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAPI 
{
   @XmlElements(
      {
         @XmlElement(name = "ResponseCode"),
         @XmlElement(name = "ResultCode")
      })
   private String responseCode;
   // ...
}

在这种情况下,在解组(xml - &gt;对象)期间将使用ResponseCodeResultCode,在编组期间(object - &gt; xml)仅使用ResultCode

所以你可以像

那样解组XML
<responseAPI>
    <ResponseCode>404</ResponseCode>
</responseAPI>  

编组后的对象看起来像

<responseAPI>
    <ResultCode>404</ResultCode>
</responseAPI>

答案 1 :(得分:3)

注意:

answer given by Ilya可以正常工作,但不能保证在JAXB的所有实现中工作,甚至不能在单个JAXB实现的各个版本中工作。当决定哪个元素编组取决于值的类型时,@XmlElements注释很有用(参见:http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html)。在您的用例中,ResponseCodeResultCode元素都对应于类型String,解组将始终正常工作,但选择要输出的元素是任意的。一些JAXB Impls可能最后指定了胜利,但其他人可能很容易获得第一次胜利。


您可以通过利用@XmlElementRef来完成以下操作。

Java模型

<强> ResponseAPI

我们会将responseCode属性从String类型更改为JAXBElement<String>JAXBElement允许我们存储元素名称和值。

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

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

    @XmlElementRefs({
        @XmlElementRef(name = "ResponseCode"),
        @XmlElementRef(name = "ResultCode")
    })
    private JAXBElement<String> responseCode;

    public JAXBElement<String> getResponseCode() {
        return responseCode;
    }

    public void setResponseCode(JAXBElement<String> responseCode) {
        this.responseCode = responseCode;
    }

}

<强>的ObjectFactory

我们在@XmlElementRef类上使用的ResponseAPI注释对应于使用@XmlElementDecl注释的类上的@XmlRegistry注释。传统上这个类称为ObjectFactory,但你可以随意调用它。

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="ResponseCode")
    public JAXBElement<String> createResponseCode(String string) {
        return new JAXBElement<String>(new QName("ResponseCode"), String.class, string);
    }

    @XmlElementDecl(name="ResultCode")
    public JAXBElement<String> createResultCode(String string) {
        return new JAXBElement<String>(new QName("ResultCode"), String.class, string);
    }

}

演示代码

<强> input.xml中

<responseAPI>
    <ResponseCode>ABC</ResponseCode>
</responseAPI>

<强>演示

创建JAXBContext时,我们需要确保包含包含@XmlElementDecl注释的类。

import java.io.File;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("Scratch/src2/forum24554789/input.xml");
        ResponseAPI responseAPI = (ResponseAPI) unmarshaller.unmarshal(xml);

        ObjectFactory objectFactory = new ObjectFactory();
        String responseCode = responseAPI.getResponseCode().getValue();
        JAXBElement<String> resultCodeJAXBElement = objectFactory.createResultCode(responseCode);
        responseAPI.setResponseCode(resultCodeJAXBElement);

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

}

<强>输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<responseAPI>
    <ResultCode>ABC</ResultCode>
</responseAPI>