Выделение XML в Java с элементами "anyAttribute" и "any" в XSD
Я застрял с этой проблемой 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>
Вот пример полного XML-файла, который мне нужно создать из Java: SUBMISSION_REQUEST.xml.
Вот краткое изложение того, что я сделал:
- Сгенерировал классы Java из двух задействованных файлов XSD. Используются два 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
- Создан модульный тест, устанавливающий значения для объекта GovTalkMessage на основе значений из SUBMISSION_REQUEST.xml
- (Это где у меня была проблема). Устанавливая значения для Body, мне нужно сформировать IRenvelope для завершения xml, но я получил класс Body с неполными установщиками (нет IRenvelope).
Основным xml-конвертом является GovTalkMessage, который используется для отправки сообщений в HMRC правительства Великобритании. Похоже, что конверт GovTalkMessage был повторно использован, что позволяет принимать различные сообщения, в частности, с помощью тега Body.
Моя дилемма заключается в том, что внутри тега Body мне нужно иметь возможность разместить IRenvelope, исходящий из FullPaymentSubmission-2016-v1-2.xsd, в качестве XML-схемы для IRenvelope, и иметь возможность устанавливать значения, связанные с этим объектом в Java, чтобы Я мог бы создать весь XML, как видно на SUBMISSION_REQUEST.xml
XSD для GovTalkMessage - это envelope-v2-0-HMRC.xsd. Вы увидите, что под анонимным типом Body является anyAttribute и any. но мне нужен IRenvelope.
Для более ясного объяснения я сгенерировал Java-классы для envelope-v2-0-HMRC.xsd и дал мне GovTalkMessage.java, который является основным эквивалентом конверта xov 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
Основная проблема связана с элементом "Body" GovTalkMessage, который использует ##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>
Сгенерировал соответствующие Java-классы для envelope-v2-0-HMRC.xsd и получил код для GovTalkMessage.java (я предоставил только фрагмент, связанный с элементом body).
Очевидно, что не было метода установки для перенаправления значений, связанных с 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);
Я попытался установить getAny с экземпляром Java-класса IRenvelope, сгенерированным из FullPaymentSubmission-2016-v1-2.xsd, но получил ошибку ниже:
Ошибка:
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 ответ
Ответ
Вам просто нужно создать свой 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>