Как заставить XStream парсить частичный ввод из StAX

Я новичок в Stax и XStream. Я пытаюсь демаршалировать некоторые общие элементы из огромного XML-потока (может потребоваться от 1,5 до 2,5 миллионов элементов)

Я попытался Stax проанализировать поток, чтобы добраться до интересующего элемента, а затем вызвать xStream для отмены маршалинга XML до EndElement.

XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(fis);
            while (reader.hasNext()) {
                if (reader.isStartElement() && reader.getLocalName().toLowerCase().equals("person")) {
                    break;
                }
                reader.next();
            }

            StaxDriver sd = new StaxDriver();
            AbstractPullReader rd = sd.createStaxReader(reader);
            XStream xstream = new XStream(sd);
            xstream.registerConverter(new PersonConverter());
            Person p = (Person) xstream.unmarshal(rd);

Создаю тестовый ввод <Persons> <Person> <name>A</name> </Person> <Person> <name>B</name> </Person> <Person> <name>C</name> </Person> </Persons>

Проблема в том, что первый мой конвертер не вызывается. Во-вторых, я получаю CannotResolveClassException для элемента «name» в Person, а XStream не создает мой объект Person. Что я пропустил в своем коде?


person Bassam    schedule 18.05.2017    source источник
comment
Привет, я также сталкиваюсь с аналогичной проблемой при использовании XMLStreamReader. Я не знаю, как Look Ahead использовать XMLStreamReader. Вы нашли на это ответ? Если да, то просьба дать свой ответ. Я также разместил здесь свой вопрос: stackoverflow.com/questions/67667516/   -  person BATMAN_2008    schedule 25.05.2021


Ответы (1)


Когда вы создаете экземпляр AbstractPullReader, он считывает первое событие открытого элемента из потока, устанавливая «корневой» элемент. Поскольку вы уже прочитали первое Person событие, оно перейдет к следующему (name), которое он не знает, как демаршалировать.

Чтобы ваш пример заработал, вам нужно сделать две вещи:

Сначала укажите псевдоним имени элемента Person для вашего класса java.

xstream.alias("Person", Person.class);

Во-вторых, перемещайте курсор SAX только до элемента перед тем, который вы хотите прочитать:

while (reader.hasNext()) {         
    if (reader.isStartElement() && reader.getLocalName().equals("Persons")) {            
        break;
    }
    reader.next();
}
person teppic    schedule 19.05.2017
comment
Спасибо. Это работает, но тогда я вынужден останавливать один элемент перед тем, который я хотел бы проанализировать. Что, если Persons может содержать несколько необязательных элементов в качестве своих первых дочерних элементов. API считывателей StAX не поддерживает метод прогнозирования. - person Bassam; 19.05.2017