XStream: Сворачивание иерархии XML, поскольку я анализирую

У меня есть XML-документ (сгенерированный формами Adobe XFA), который содержит данные как следующее:

<Position>
   <PositionBorder>
       <Title/>
       <StartDate/>
       <EndDate/>
   </PositionBorder>
</Position>

Так как этот файл определяется в другом месте, я не имею право изменять формат XML, который я получаю.

В моем коде Java я создаю класс Положения, который содержит Заголовок, Запустите и Даты окончания.

Моя проблема, когда я использую XStream для парсинга файла, это хочет, чтобы класс PositionBorder исполнил обязанности и даты. Я хочу в основном проигнорировать границу и поместить все поля в класс Положения.

То, что я действительно хотел бы сделать, использовать что-то как convertAnother метод для преобразования ребенка элемента положения. Я пытался сделать просто это, и это перестало работать, потому что мой PositionConverter вызван PositionBorder (когда я называю convertAnother).

У кого-либо есть какие-либо подсказки, как иметь дело со сворачиванием структуры XML при парсинге?

6
задан John Saunders 24 February 2010 в 00:00
поделиться

1 ответ

Сделать кастомный конвертер не так уж и сложно. Это немного длинный пример, но я надеюсь, что он достаточно прост, чтобы понять суть того, что вам нужно сделать:

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public final class ConverterTest {
    public static void main(String[] args) {
        XStream xstream = new XStream();
        xstream.autodetectAnnotations(true);
        xstream.registerConverter(new PositionConverter());

        final Position position = new Position();
        position.setTitle("The Title");
        position.setStartDate("The Start Date");
        position.setEndDate("The End Date");

        final String xml = xstream.toXML(position);
        System.out.println("Generated XML:");
        System.out.println(xml);

        final Position genPosition = (Position) xstream.fromXML(xml);
        System.out.println("Generated Position:");
        System.out.println("\tTitle: " + genPosition.getTitle());
        System.out.println("\tStart Date: " + genPosition.getStartDate());
        System.out.println("\tEnd Date: " + genPosition.getEndDate());
    }

    @XStreamAlias("Position")
    private static class Position {
        public String getEndDate() {
            return endDate;
        }

        public void setEndDate(String endDate) {
            this.endDate = endDate;
        }

        public String getStartDate() {
            return startDate;
        }

        public void setStartDate(String startDate) {
            this.startDate = startDate;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        private String title;
        private String startDate;
        private String endDate;
    }

    private static class PositionConverter implements Converter {
        public boolean canConvert(Class clazz) {
            return Position.class == clazz;
        }

        public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
            Position position = (Position)value;
            writer.startNode("PositionBorder");

            writer.startNode("Title");
            writer.setValue(position.getTitle());
            writer.endNode();

            writer.startNode("StartDate");
            writer.setValue(position.getStartDate());
            writer.endNode();

            writer.startNode("EndDate");
            writer.setValue(position.getEndDate());
            writer.endNode();

            writer.endNode();
        }

        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Position position = new Position();
            // move it to <PositionBorder> tag.
            reader.moveDown();
            // now move it to <Title> tag.
            reader.moveDown();
            String title = reader.getValue();
            position.setTitle(title);
            reader.moveUp(); // moves back to <PositionBorder>

            reader.moveDown(); // should move down to <StartDate> tag
            String startDate = reader.getValue();
            position.setStartDate(startDate);
            reader.moveUp(); // move back to <PositionBorder>

            reader.moveDown(); // should move down to <EndDate> tag
            String endDate = reader.getValue();
            position.setEndDate(endDate);
            reader.moveUp(); // move back to <PositionBorder>


            return position;
        }
    }
}

Попробуйте запустить его и посмотрите, что произойдет. Конечно, вам нужно будет изменить его в соответствии с вашими типами - я просто использовал строки для всех полей Position (и я уверен, что ваш класс Position также не вложен), но преобразовал из String к дате (или чему-то еще) должно быть довольно тривиальным.

Одна вещь, на которую вы захотите обратить внимание (а я, возможно, не понял полностью прямо в моем примере), - это сопоставление ваших вызовов reader.moveDown () и reader.moveUp (). (И, если вы собираетесь выполнять какой-либо маршаллинг вместо простого демаршалинга - чего я не ожидаю от вашего вопроса - вы также захотите сопоставить свои вызовы writer.startNode () и writer.endNode () Скорее всего, это не вызовет никаких проблем с этим примером, но я уверен, что это вызовет проблемы, если вы делаете что-то большее или обрабатываете несколько файлов с одним и тем же экземпляром XStream или Converter. Кроме того, если вы попробуете reader.moveDown () из недопустимого места, вы получите действительно неприятное исключение - это должно быть довольно очевидно.

Мне пришлось немного поэкспериментировать с методами moveUp / moveDown, чтобы разместить их в нужных местах, поэтому я уверен, что вам нужно будет протестировать их и настроить, пока не получите то, что вам нужно.

4
ответ дан 17 December 2019 в 07:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: