【问题标题】:JAX-B customized XML outputJAX-B 自定义 XML 输出
【发布时间】:2016-09-08 07:26:57
【问题描述】:

我正在使用 ECCP 协议,以便将我的 CRM 与 Elastix 呼叫中心模块集成。该协议使用如下定义的 XML 结构:

<request id="1">
   <request_type> <!-- this will be mapped to the Java request class -->
       <attributes>
       </attributes>
   </request_type>
</request>

<response id="1">
    <response_type> <!-- this will be mapped to the Java response class -->
        <attributes>
        </attributes>
    </response_type>
</response>

我正在使用 JAX-B 将 XML 映射到 Java 类,但问题是我必须将 JAX-B 生成的 XML 放入每个请求的 &lt;request&gt;&lt;/request&gt; XML 中,并在每个响应中从 &lt;response&gt;&lt;/response&gt; 中提取内容因为 ECCP 协议定义了每个请求和响应都需要嵌套到各自的元素中。

这是我用来执行此操作的代码:

document = createDocument();
Element requestWrapper = document.createElement("request");
requestWrapper.setAttribute("id", String.valueOf(wrapped.getId()));
document.appendChild(requestWrapper);

JAXBContext jc = JAXBContext.newInstance(wrapped.getClass());
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(wrapped, requestWrapper);

举例:

ECCP 的协议操作之一是 JAX-B 映射到这样的类(省略了 getter 和 setter):

@XmlRootElement(name = "loginagent")
@XmlAccessorType(XmlAccessType.FIELD)
public class EccpLoginAgentRequest implements IEccpRequest {

    @XmlElement(name = "agent_number")
    private String agentNumber;

    @XmlElement(name = "password")
    private String password;
}

JAX-B 输出以下内容:

<loginagent>
   <agent_number>username</agent_number>
   <password>password</password>
</loginagent>

但是 ECCP 的协议要求的是:

<request id="1"> <!-- id is an auto-increment number to identify the request -->
    <loginagent>
       <username>username</username>
       <password>password</password>
    </loginagent>
</request>

问题是:有没有其他更好的方法可以实现? 谢谢。

【问题讨论】:

    标签: java xml jaxb


    【解决方案1】:

    您可能可以查看@XmlSeeAlso 注释,它可以帮助您为请求和响应包装相同的内容。对于内部部分,您可以创建单独的类并适当地映射所有字段。我希望这对您有所帮助。

    编辑: 很抱歉回复时间长。您需要创建一个内部结构定义为@XmlElement 的包装类。以下是实现 XML 结构的方法:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement(name = "request")
    public class RequestWrapper {
    
    @XmlElement(name = "loginagent", required = true)
    protected EccpLoginAgentRequest loginagent;
    
    public EccpLoginAgentRequest getLoginagent() {
        return loginagent;
    }
    
    public void setLoginagent(EccpLoginAgentRequest loginagent) {
        this.loginagent = loginagent;
    }
    }
    

    这里是 EccpLoginAgentRequest 结构:

    @XmlAccessorType(XmlAccessType.FIELD)
    public class EccpLoginAgentRequest {
    
    @XmlElement(name = "agent_number")
    private String agentNumber;
    
    @XmlElement(name = "password")
    private String password;
    
    // getters and setters omitted
    }
    

    因此,您可以像这样打印所需的 XML:

    JAXBContext jaxbContext = JAXBContext.newInstance(Wrapper.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,    true);
    
    EccpLoginAgentRequest request = new EccpLoginAgentRequest();
    request.setAgentNumber("1");
    request.setPassword("pass");
    
    Wrapper wrapper = new Wrapper();
    wrapper.setLoginagent(request);
    
    jaxbMarshaller.marshal(wrapper, System.out);
    

    它会给你以下输出:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <request>
        <loginagent>
            <agent_number>1</agent_number>
            <password>pass</password>
        </loginagent>
    </request>
    

    【讨论】:

    • 好的,我查看了@XmlSeeAlso 注释文档,但我会改进我的问题以更好地解释问题。
    • 如果您能再次检查问题,我会很高兴。提前致谢。
    • 再次感谢@reallol,但它仅在我发送 EccpLoginAgentRequest 对象时才有效,而我真正需要的是能够从任何扩展 EccpRequest 的类发送对象。
    【解决方案2】:

    我在这篇文章中找到了解决此问题的方法:XML element with attribute and content using JAXB

    所以我将 EccpRequestWrapper 对象映射为如下:

    @XmlRootElement(name = "request")
    public class EccpRequestWrapper {
        @XmlAttribute
        private Long id;
    
        @XmlAnyElement
        private IEccpRequest request;
    }
    

    然后我的请求 JAX-B 以 ECCP 协议要求的方式输出我的请求。 @XmlAttribute@XmlAnyElement 注释起到了作用。

    <request id="1">
       <login>
          <username>user</username>
          <password>****</password>
       </login>
    </request>
    

    一个好的 JAXB 指南可以在这里找到https://jaxb.java.net/guide/Mapping_interfaces.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多