Marshalling XML to Java with elements “anyAttribut

2020-04-12 01:13发布

问题:

I am stuck with this XSD and JAXB problem... Please help me out...

What I need to achieve is to fully generate the xml below.

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

Here's an example of the full xml file I need to create from Java: SUBMISSION_REQUEST.xml .

Here's a summary of what I have done:

  1. Generated the Java classes from the two XSD files involved. The two XSD files involved are: envelope-v2-0-HMRC.xsd - link to file: https:// drive.google.com/file/d/0Bwota60eLfeIN1duSGVhTE8xOWM/view?usp=sharing FullPaymentSubmission-2016-v1-2.xsd - link to file: https:// drive.google.com/file/d/0Bwota60eLfeIbUtMN1RaMmt0LWM/view?usp=sharing
  2. Created a unit test setting the values for GovTalkMessage object based on the values from SUBMISSION_REQUEST.xml
  3. (This is where I had the problem). Setting the values for the Body, I need to form the IRenvelope to complete the xml, but what I got is a Body class with incomplete setters (there is no IRenvelope).

The main xml envelope is GovTalkMessage which is used to send messages to UK Government's HMRC. It appears that the GovTalkMessage envelope has been made reusable that it can accept different messages by particularly using the Body tag.

My dilemma is that inside the Body tag I need to be able to place IRenvelope coming from FullPaymentSubmission-2016-v1-2.xsd as the XML Schema for the IRenvelope, and be able to set the values associated to this object in Java so that I could create the whole xml as seen on SUBMISSION_REQUEST.xml

The XSD for the GovTalkMessage is envelope-v2-0-HMRC.xsd. You will see that what is under the anonymous Body type is anyAttribute and any. but what I need is IRenvelope.

To explain more clearly, I've generated the Java classes for envelope-v2-0-HMRC.xsd and gave me the GovTalkMessage.java which is the main equivalent xml GovTalkMessage envelope I need to set values to.

Below are the xjc commands I used:

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

The main problem is with the GovTalkMessage "Body" element that uses ##any and 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>

Generated the corresponding Java classes for envelope-v2-0-HMRC.xsd and got the code for GovTalkMessage.java (I only provided the snippet related to the "body" element).

Obviously there was no setter method to redirectly set the values related to IRenvelope so that I could complete the build of the 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;
    }

I only see the getAny and getOtherAttributes which I have played around and didn't work.

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

I tried setting getAny with an instance of IRenvelope java class generated from FullPaymentSubmission-2016-v1-2.xsd but got the error below:

Error:

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)

I hope someone could help me shed some light on how to correctly solve this problem.

回答1:

Answer

You should just need to create your JAXBContext on a colon delimited String with the two generated packages:

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

Demo Code

Then when I run:

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

}

I get the following as output:

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