Работа с плохо разработанным XML с помощью JAXB - PullRequest
5 голосов
/ 07 июля 2011

В настоящее время я работаю над заменой устаревшей системы на JAXB, и у меня возникла проблема с анализом XML.Основным требованием системы является то, что она должна быть заменой, поэтому я не могу изменить формат XML.Ниже приведен раздел XML, который доставляет мне проблемы.

<xx>
    <s1>
        <X>-9999</X>
        <Y>-9999</Y>
    </s1>
    <s2>
        <X>-9999</X>
        <Y>-9999</Y>
   </s2>
</xx>

Проблема с XML заключается в том, что все объекты s # абсолютно одинаковы, и их может быть до 256.Есть ли способ в JAXB аннотировать такой тег, или мне нужно создать 256 отдельных аннотаций?Любая помощь будет наиболее ценной.

Вот код Java для объекта xx.Примечание: объект изначально был запрограммирован с пониманием, что будет только 2 объекта s #, но с тех пор он изменился.

@XmlRootElement(name="xx")

public class XMLXx implements Serializable {

    private static final long serialVersionUID = 4064597372833234503L;

    private XMLSite siteOne;
    private XMLSite siteTwo;

    @XmlElement(name="s1")
    public XMLSite getSiteOne() {
        return siteOne;
    }

    public void setSiteOne(XMLSite s1) {
        this.siteOne = s1;
    }

    @XmlElement(name="s2")
    public XMLSite getSiteTwo() {
        return siteTwo;
    }

    public void setSiteTwo(XMLSite s2) {
        this.siteTwo = s2;
    }
}

А вот объект XMLSite:

public class XMLSite implements Serializable {

    private static final long serialVersionUID = -4374405403222014476L;

    private Integer x;
    private Integer y;

    @XmlElement(name="X")
    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    @XmlElement(name="Y")
    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }
}

Ответы [ 4 ]

7 голосов
/ 08 июля 2011

Если вы хотите обработать элементы s# как коллекцию:

import java.io.Serializable;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="xx")
public class XMLXx implements Serializable {

    private static final long serialVersionUID = 4064597372833234503L;

    private List<XMLSite> sites;

    @XmlElement(name="s")
    public List<XMLSite> getSites() {
        return sites;
    }

    public void setSites(List<XMLSite> sites) {
        this.sites = sites;
    }

}

Тогда вы могли бы сделать что-то вроде того, чтобы обмануть JAXB, думая, что все элементы (s1, s2 и т. Д.) Фактически называются s:

import java.io.FileInputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml"));
        xsr = new SiteStreamReaderDelegate(xsr);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        XMLXx object = (XMLXx) unmarshaller.unmarshal(xsr);
        System.out.println(object.getSites().size());

    }

    private static class SiteStreamReaderDelegate extends StreamReaderDelegate {

        public SiteStreamReaderDelegate(XMLStreamReader xsr) {
            super(xsr);
        }

        @Override
        public String getLocalName() {
            String localName = super.getLocalName();
            if(localName.startsWith("s")) {
                return "s";
            }
            return localName;
        }

    }
}

Подобный пример см .:

3 голосов
/ 08 июля 2011

JaxB не поддерживает «динамические» теги. Поскольку их может быть только 256, используйте скрипт для генерации источника.

3 голосов
/ 08 июля 2011

Нет, я так не думаю, не со стандартным JAXB.В принципе, вы можете использовать @XmlMixed, но вы все равно получите кучу объектов DOM Element, а не связанных классов.Однако, некоторые проприетарные расширения JAXB, такие как MOXy, могли бы справиться с этим.

Это не очень хороший вариант использования для JAXB.Как вы говорите, XML плохо спроектирован.Вам было бы лучше проанализировать это вручную (например, с помощью STAX или DOM) и самостоятельно построить нужную объектную модель.

0 голосов
/ 08 июля 2011

Напишите мета-XSD в freemarker / speed или тому подобное.Он может определить 256 типов как подтипы некоторого родительского типа, используя цикл for.Если вы хотите полностью автоматизировать, вы можете написать плагин maven для генерации XSD из freemarker и запуска generate-sources для результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...