使用XSD中的元素“anyAttribute”和“any”将XML编组为Java

时间:2015-02-06 08:34:07

标签: 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
  3. 中的值设置GovTalkMessage对象的值
  4. (这是我遇到问题的地方)。设置Body的值,我需要形成IRenvelope来完成xml,但我得到的是一个Body类,其中包含不完整的setter(没有IRenvelope)。
  5. 主要的xml信封是GovTalkMessage,用于向英国政府的HMRC发送消息。似乎GovTalkMessage信封已经可重复使用,它可以通过特别使用Body标签接受不同的消息。

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

    GovTalkMessage的XSD是envelope-v2-0-HMRC.xsd。您将看到匿名Body类型下的内容是 anyAttribute any 。但我需要的是IRenvelope。

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

    以下是我使用的xjc命令:

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

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

    主要问题在于 GovTalkMessage &#34; Body&#34;使用 ## any xsd: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的代码(我只提供了与&#34; body&#34相关的代码段;元素)。

    显然没有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)
    

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

1 个答案:

答案 0 :(得分:0)

答案

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

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>