java - 使用 XSD 中的元素 "anyAttribute"和 "any"将 XML 编码为 Java

标签 java xml xsd jaxb marshalling

我被这个 XSD 和 JAXB 问题困住了...请帮助我...

我需要实现的是完全生成下面的xml。

<?xml version="1.0"?>
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/CM/envelope">
        ....
    <Body>
        <IRenvelope xmlns="http://www.govtalk.gov.uk/taxation/PAYE/RTI/FullPaymentSubmission/15-16/1">
            ....
        </IRenvelope>
    </Body>
</GovTalkMessage>

这是我需要从 Java 创建的完整 xml 文件的示例:SUBMISSION_REQUEST.xml .

这是我所做的总结:

  1. 从涉及的两个 XSD 文件生成 Java 类。涉及的两个XSD文件是: envelope-v2-0-HMRC.xsd - 文件链接:https://drive.google.com/file/d/0Bwota60eLfeIN1duSGVhTE8xOWM/view?usp=sharing FullPaymentSubmission-2016-v1-2.xsd - 文件链接:https://drive.google.com/file/d/0Bwota60eLfeIbUtMN1RaMmt0LWM/view?usp=sharing
  2. 创建了一个单元测试,根据 SUBMISSION_REQUEST.xml 中的值设置 GovTalkMessage 对象的值
  3. (这是我遇到问题的地方)。设置 Body 的值,我需要形成 IRenvelope 来完成 xml,但我得到的是一个带有不完整 setter 的 Body 类(没有 IRenvelope)。

主要的 xml 信封是 GovTalkMessage,用于向英国政府的 HMRC 发送消息。似乎 GovTalkMessage 信封已变得可重复使用,它可以通过特别使用 Body 标签来接受不同的消息。

我的难题是,在 Body 标签内,我需要能够将来自 FullPaymentSubmission-2016-v1-2.xsd 的 IRenvelope 作为 XML 架构IRenvelope,并能够在 Java 中设置与此对象关联的值,以便我可以创建整个 xml,如 SUBMISSION_REQUEST.xml 所示

GovTalkMessage 的 XSD 是 envelope-v2-0-HMRC.xsd。你会看到匿名Body类型下的是anyAttributeany。但我需要的是 IRenvelope。

为了更清楚地解释,我已经为 envelope-v2-0-HMRC.xsd 生成了 Java 类,并为我提供了 GovTalkMessage.java,这是我需要为其设置值的主要等效 xml GovTalkMessage 信封。

以下是我使用的 xjc 命令:

xjc -p com.rti.rim2016.v1_2.envelope 信封-v2-0-HMRC.xsd

xjc -p com.rti.rim2016.v1_2.fps FullPaymentSubmission-2016-v1-2.xsd

主要问题在于 GovTalkMessage“Body”元素,该元素使用 ##anyxsd:anyAttribute

    <xsd:element minOccurs="0" maxOccurs="1" name="Body">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:anyAttribute namespace="##any" processContents="strict"/>
      </xsd:complexType>
    </xsd:element>

envelope-v2-0-HMRC.xsd生成了相应的Java类,并得到了GovTalkMessage.java的代码(我只提供了与“body”元素相关的片段)。

显然没有 setter 方法来重定向设置与 IRenvelope 相关的值,以便我可以完成 XML 的构建。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "envelopeVersion",
    "header",
    "govTalkDetails",
    "body"
})
@XmlRootElement(name = "GovTalkMessage", namespace = "http://www.govtalk.gov.uk/CM/envelope")
public class GovTalkMessage {

    @XmlElement(name = "Body", namespace = "http://www.govtalk.gov.uk/CM/envelope")
    protected GovTalkMessage.Body body;
    ....

    public GovTalkMessage.Body getBody() {
        return body;
    }

    /**
     * Sets the value of the body property.
     * 
     * @param value
     *     allowed object is
     *     {@link GovTalkMessage.Body }
     *     
     */
    public void setBody(GovTalkMessage.Body value) {
        this.body = value;
    }

我只看到 getAny 和 getOtherAttributes,我试过但没有用。

    //Body
    Body body = new Body();
    IRenvelope irEnvelope = new IRenvelope();
    body.getAny().add(irEnvelope);
    govTalkMessage.setBody(body);

我尝试使用从 FullPaymentSubmission-2016-v1-2.xsd 生成的 IRenvelope java 类实例设置 getAny,但出现以下错误:

错误:

javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: class com.rti.rim2016.v1_2.fps.generated.IRenvelope nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class com.upraxis.rti.rim2016.v1_2.fps.generated.IRenvelope nor any of its super class is known to this context.]
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:116)

我希望有人能帮助我阐明如何正确解决这个问题。

最佳答案

回答

您应该只需要使用两个生成的包在冒号分隔的 String 上创建您的 JAXBContext:

JAXBContext jc = JAXBContext.newInstance("com.rti.rim2016.v1_2.fps:com.rti.rim2016.v1_2.envelope");

演示代码

然后当我运行时:

import javax.xml.bind.*;
import com.rti.rim2016.v1_2.fps.*;
import com.rti.rim2016.v1_2.envelope.GovTalkMessage;
import com.rti.rim2016.v1_2.envelope.GovTalkMessage.Body;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance("com.rti.rim2016.v1_2.fps:com.rti.rim2016.v1_2.envelope");

        GovTalkMessage govTalkMessage = new GovTalkMessage();

        Body body = new Body();
        IRenvelope irEnvelope = new IRenvelope();
        body.getAny().add(irEnvelope);
        govTalkMessage.setBody(body);

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

}

我得到以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:GovTalkMessage xmlns="http://www.govtalk.gov.uk/taxation/PAYE/RTI/FullPaymentSubmission/15-16/1" xmlns:ns2="http://www.govtalk.gov.uk/CM/envelope" xmlns:ns3="http://www.w3.org/2000/09/xmldsig#">
    <ns2:Body>
        <IRenvelope/>
    </ns2:Body>
</ns2:GovTalkMessage>

关于java - 使用 XSD 中的元素 "anyAttribute"和 "any"将 XML 编码为 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28361603/

相关文章:

Java对象锁等于或同步等于? (对哈希码也有效)

c# - 通过 xml 进行搜索的最快方法是什么

php - XML 使 PHP 出现意外的字符串错误

iphone - 如何使用 iPhone sdk 将 XML 字符串转换为 JSON

XML 命名空间和属性

c# - 启动 Contract First WCF 或 Web 服务的最佳方式?

java - 包含 Google Cloud Client 库后在 Android Studio 中构建错误

java - 覆盖java配置中的bean定义

XML 架构 : root element

java - 带有 AWTEventListener 的全局事件监听器以及如何从中提取 MouseEvent