MOXy JAXB: как отобразить несколько элементов тега XML в одно и то же свойство компонента JAVA - PullRequest
1 голос
/ 21 марта 2012

Я пытаюсь разобрать XML-файл с помощью MOXy JAXB. У меня есть набор классов, которые уже созданы, и я использую Xpath для сопоставления каждого элемента XML, который мне нужен, с моей моделью.

У меня есть XML-файл, подобный этому:

<?xml version="1.0" encoding="UTF-8"?>
<fe:Facturae xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    xmlns:fe="http://www.facturae.es/Facturae/2009/v3.2/Facturae">
    <Parties>
        <SellerParty>
            <LegalEntity>
                <CorporateName>Company Comp SA</CorporateName>
                <TradeName>Comp</TradeName>
                <ContactDetails>
                    <Telephone>917776665</Telephone>
                    <TeleFax>917776666</TeleFax>
                    <WebAddress>www.facturae.es</WebAddress>
                    <ElectronicMail>facturae@mityc.es</ElectronicMail>
                    <ContactPersons>Fernando</ContactPersons>
                    <CnoCnae>28000</CnoCnae>
                    <INETownCode>2134AAB</INETownCode>
                    <AdditionalContactDetails>Otros datos</AdditionalContactDetails>
                </ContactDetails>
            </LegalEntity>
        </SellerParty>
        <BuyerParty>
            <Individual>
                <Name>Juana</Name>
                <FirstSurname>Mauriño</FirstSurname>
                <OverseasAddress>
                    <Address>Juncal 1315</Address>
                    <PostCodeAndTown>00000 Buenos Aires</PostCodeAndTown>
                    <Province>Capital Federal</Province>
                    <CountryCode>ARG</CountryCode>
                </OverseasAddress>
                <ContactDetails>
                    <Telephone>00547775554</Telephone>
                    <TeleFax>00547775555</TeleFax>
                </ContactDetails>
            </Individual>
        </BuyerParty>
    </Parties>
</fe:Facturae>

Тогда у меня есть моя модель:

@XmlRootElement(namespace="http://www.facturae.es/Facturae/2009/v3.2/Facturae", name="Facturae")
public class Facturae implements BaseObject, SecuredObject, CreationDataAware {
    @XmlPath("Parties/SellerParty")
    private Party sellerParty;

    @XmlPath("Parties/BuyerParty")
    private Party buyerParty;
}

public class Party implements BaseObject, SecuredObject, CreationDataAware {
@XmlPath("LegalEntity/ContactDetails")
    private ContactDetails contactDetails;
}

Как видите, <ContactDetails></ContactDetails> присутствует в <SellerParty></SellerParty> и <BuyerParty></BuyerParty>, но эти два тега совместно используют один и тот же объект JAVA (Party). С помощью предыдущего сопоставления (@XmlPath ("LegalEntity / ContactDetails")) я могу правильно передать информацию ContactDetails в SellerParty, но я также хочу передать ContactDetails в <BuyerParty> одновременно.

Я пытался что-то подобное:

@XmlPaths(value = { @XmlPath("LegalEntity/ContactDetails"),@XmlPath("Individual/ContactDetails") })
    private ContactDetails contactDetails;

но это не работает.

Ребята, можете ли вы дать мне руку?

Большое спасибо.

1 Ответ

0 голосов
/ 21 марта 2012

Вы можете использовать XmlAdapter для этого варианта использования:

PartyAdapter

Мы будем использовать XmlAdapter для преобразования экземпляра Party вдругой тип объекта AdaptedParty.AdaptedParty будет иметь два свойства, соответствующих каждому свойству в Party (по одному для каждой возможности отображения).Мы воспользуемся возможностью предварительно инициализировать экземпляр XmlAdapter, чтобы установить для него экземпляр Facturae.Мы будем использовать экземпляр Facturae, чтобы определить, является ли экземпляр Party, который мы обрабатываем, sellerParty или buyerParty.

package forum9807536;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;

public class PartyAdapter extends XmlAdapter<PartyAdapter.AdaptedParty, Party> {

    private Facturae facturae;

    public PartyAdapter() {
    }

    public PartyAdapter(Facturae facturae) {
        this.facturae = facturae;
    }

    @Override
    public Party unmarshal(AdaptedParty v) throws Exception {
        Party party = new Party();
        if(v.individualName != null) {
            party.setName(v.individualName);
            party.setContactDetails(v.individualContactDetails);
        } else {
            party.setName(v.sellPartyName);
            party.setContactDetails(v.sellerPartyContactDetails);
        }
        return party;
    }

    @Override
    public AdaptedParty marshal(Party v) throws Exception {
        AdaptedParty adaptedParty = new AdaptedParty();
        if(null == facturae || facturae.getSellerParty() == v) {
            adaptedParty.sellPartyName = v.getName();
            adaptedParty.sellerPartyContactDetails = v.getContactDetails();
        } else {
            adaptedParty.individualName = v.getName();
            adaptedParty.individualContactDetails = v.getContactDetails();
        }
        return adaptedParty;
    }

    public static class AdaptedParty {

        @XmlPath("Individual/Name/text()")
        public String individualName;
        @XmlPath("Individual/ContactDetails")
        public ContactDetails individualContactDetails;

        @XmlPath("LegalEntity/CorporateName/text()")
        public String sellPartyName;
        @XmlPath("LegalEntity/ContactDetails")
        public ContactDetails sellerPartyContactDetails;
    }

}

Сторона

Мы будем использовать @XmlJavaTypeAdapter, чтобы связать PartyAdapter с Party классом:

package forum9807536;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(PartyAdapter.class)
public class Party implements BaseObject, SecuredObject, CreationDataAware {
    private String name;
    private ContactDetails contactDetails;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ContactDetails getContactDetails() {
        return contactDetails;
    }

    public void setContactDetails(ContactDetails contactDetails) {
        this.contactDetails = contactDetails;
    }

}

Демо

Следующий демонстрационный коддемонстрирует, как установить предварительно инициализированный XmlAdapter на Marshaller:

package forum9807536;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Facturae.class);

        File xml = new File("src/forum9807536/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Facturae facturae = (Facturae) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setAdapter(new PartyAdapter(facturae));
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(facturae, System.out);
    }

}

Выход

Ниже приведен вывод демонстрационного кода, который соответствуетчасть вашей модели, которую я нанес на карту.

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Facturae xmlns:ns0="http://www.facturae.es/Facturae/2009/v3.2/Facturae">
   <Parties>
      <BuyerParty>
         <Individual>
            <Name>Juana</Name>
            <ContactDetails/>
         </Individual>
      </BuyerParty>
      <SellerParty>
         <LegalEntity>
            <CorporateName>Company Comp SA</CorporateName>
            <ContactDetails/>
         </LegalEntity>
      </SellerParty>
   </Parties>
</ns0:Facturae>

Для получения дополнительной информации

...