Частичная распаковка XML с использованием JAXB для пропуска некоторых xmlElement

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

Пример XML выглядит следующим образом:

<Example id="10" date="1970-01-01" version="1.0"> 
    <Properties>...</Properties>
    <Summary>...</Summary>
    <RawData>
        <Document id="1">...</Document>
        <Document id="2">...</Document>
        <Document id="3">...</Document>
        ------
        ------
    </RawData>
    <Location></Location>
    <Title></Title>
    ----- // more elements
</Example>

У меня есть два варианта использования:

  • распаковать в пример объекта, который содержит свойства, сводки, необработанные данные и т. д., не пропуская какие-либо необработанные данные. (уже сделал эту часть)
  • распаковать в пример объекта, который исключает RawData. Элементы, вложенные в RawData, очень велики, поэтому не хочу читать это в этом случае использования.

Теперь я хочу демаршалировать XML, чтобы можно было пропустить RawData. Я попробовал метод, представленный по этой ссылке.

Использование техники, представленной в приведенной выше ссылке, также пропускает все элементы, идущие после RawData.


person Pratham    schedule 20.05.2013    source источник
comment
можно ли использовать streamFilter для пропуска элементов?   -  person Pratham    schedule 21.05.2013


Ответы (2)


Я исправил проблему с XMLEventReader с помощью следующего кода:

public class PartialXmlEventReader implements XMLEventReader {

private final XMLEventReader reader;
private final QName qName;
private boolean skip = false;

public PartialXmlEventReader(final XMLEventReader reader, final QName element) {
    this.reader = reader;
    this.qName = element;
}

@Override
public String getElementText() throws XMLStreamException {
    return reader.getElementText();
}

@Override
public Object getProperty(final String name) throws IllegalArgumentException {
    return reader.getProperty(name);
}

@Override
public boolean hasNext() {
    return reader.hasNext();
}

@Override
public XMLEvent nextEvent() throws XMLStreamException {
    while (isEof(reader.peek())) {
        reader.nextEvent();
    }

    return reader.nextEvent();
}

@Override
public XMLEvent nextTag() throws XMLStreamException {
    return reader.nextTag();
}

@Override
public XMLEvent peek() throws XMLStreamException {
    return reader.peek();
}

@Override
public Object next() {
    return reader.next();
}

@Override
public void remove() {
    reader.remove();
}

@Override
public void close() throws XMLStreamException {
    reader.close();
}

private boolean isEof(final XMLEvent e) {
    boolean returnValue = skip;
    switch (e.getEventType()) {
    case XMLStreamConstants.START_ELEMENT:
        final StartElement se = (StartElement) e;
        if (se.getName().equals(qName)) {
            skip = true;
            returnValue = true;
        }
        break;
    case XMLStreamConstants.END_ELEMENT:
        final EndElement ee = (EndElement) e;
        if (ee.getName().equals(qName)) {
            skip = false;
        }
        break;
    }
    return returnValue;
}

}

Во время Unmarshalling просто передайте этот eventReader методу unmarshaling

final JAXBContext context = JAXBContext.newInstance(classes);
    final Unmarshaller um = context.createUnmarshaller();
    Reader reader = null;
    try {
        reader = new BufferedReader(new FileReader(xmlFile));
        final QName qName = new QName("RawData");
        final XMLInputFactory xif = XMLInputFactory.newInstance();
        final XMLEventReader xmlEventReader = xif.createXMLEventReader(reader);
        final Example example =
                (Example) um.unmarshal(new PartialXmlEventReader(xmlEventReader, qName));
        }
    } finally {
        IOUtils.closeQuietly(reader);
    }
person Pratham    schedule 21.05.2013

Я надеюсь, что это поможет

try {
        // First create a new XMLInputFactory
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        // Setup a new eventReader
        InputStream in = new FileInputStream("myXml");
        XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
        // Read the XML document
        Example example = null;

        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();

            if (event.isStartElement()) {
                StartElement startElement = event.asStartElement();
                // If we have a example element we create a new example
                if (startElement.getName().getLocalPart().equals("Example")) {
                    example = new Example();
                    // We read the attributes from this tag and add the date
                    //  and id attribute to our object
                    Iterator<Attribute> attributes = startElement
                            .getAttributes();
                    while (attributes.hasNext()) {
                        Attribute attribute = attributes.next();
                        if (attribute.getName().toString().equals("date")) {
                            example.setDate(attribute.getValue());
                        } else if (attribute.getName().toString().equals("id")) {
                            example.setId(attribute.getValue());
                        }

                    }
                }

                 //get the Properties tag and add to object example
                if (event.isStartElement()) {
                    if (event.asStartElement().getName().getLocalPart()
                            .equals("Properties")) {
                        event = eventReader.nextEvent();
                        example.setProperites(event.asCharacters().getData());
                        continue;
                    }
                }
                 //get the Summary tag and add to object example
                if (event.asStartElement().getName().getLocalPart()
                        .equals("Summary")) {
                    event = eventReader.nextEvent();
                    example.setSummary(event.asCharacters().getData());
                    continue;
                }

                // when you encounter the Rawdata tag just continue
                //without adding it to the object created
                if (event.asStartElement().getName().getLocalPart()
                        .equals("Rawdata")) {
                    event = eventReader.nextEvent();
                    // don't do anything
                    continue;
                }

                //get the location tag and add to object example
                if (event.asStartElement().getName().getLocalPart()
                        .equals("Location")) {
                    event = eventReader.nextEvent();
                    example.setLocation(event.asCharacters().getData());
                    continue;
                }
                // read and add other elements that can be added
            }
            // If we reach the end of an example element/tag i.e closing tag
            if (event.isEndElement()) {
                EndElement endElement = event.asEndElement();
                if (endElement.getName().getLocalPart().equals("Example")) {
                    //do something
                }
            }

        }
    } catch (FileNotFoundException | XMLStreamException e) {
    }
person Ayodeji    schedule 20.05.2013
comment
Я не хочу повторять xml для создания каждого объекта по отдельности, поскольку мои объекты очень сложны. Итак, мы используем jaxb для автоматической привязки. - person Pratham; 21.05.2013