StAX с синтаксическим анализом JAXB XML Только синтаксический анализ первого экземпляра

Привет, у меня есть такая структура XML:

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <result>
     <name>Chrome</name>
     <version>2</version>
   </result>
  <result>
     <name>IE</name>
     <version>8</version>
   </result>
</response>

Я пытаюсь использовать staxx для анализа только того, что находится посередине с помощью JAXB. Проблема, с которой я сталкиваюсь, заключается в том, что она не получает все элементы результата. Смотрите ниже:

Выход:

response
result
name
version

Как я могу получить все объекты результата, внутри может быть любой общий объект, который я передаю? Кроме того, есть ли способ после того, как я проанализирую объект с помощью jaxb, продвинуть итератор staxx до конца (поскольку нет особого смысла анализировать остальные, когда у меня есть объект).

private static <T> List<T> unmarshallCreateResponseObject(Class<T> clazz, String xml) throws JAXBException, XMLStreamException
{

    List<T> list = new ArrayList<T>();
    XMLInputFactory xif = XMLInputFactory.newFactory();

    StringReader stringReader = new StringReader(xml);

    XMLStreamReader xsr = xif.createXMLStreamReader(stringReader);

    while (xsr.hasNext()) {
        int eventType = xsr.next();

      if(eventType == XMLStreamReader.START_ELEMENT){
          System.out.println(xsr.getLocalName());
            if(xsr.getLocalName().equals("result"))
            {
                JAXBContext jc = JAXBContext.newInstance(clazz);
                Unmarshaller unmarshaller = jc.createUnmarshaller();
                JAXBElement<T> jb = unmarshaller.unmarshal(xsr, clazz);
                list.add(jb.getValue());
            }
      }

    }

    xsr.close();

    return list;

}

person CodyK    schedule 10.03.2015    source источник


Ответы (1)


Из документации unmarshaller (выделено мной)

<T> JAXBElement<T> Unmarshaller.unmarshal(XMLStreamReader reader, Class declaredType)

Отмените преобразование корневого элемента в JAXB, сопоставленный с объявленным типом, и верните результирующее дерево контента.

Этот метод реализует демаршалирование по объявленному типу.

Этот метод предполагает, что синтаксический анализатор работает с событием START_DOCUMENT или START_ELEMENT. Разупорядочение будет выполняться от этого начального события до соответствующего конечного события. Если этот метод завершается успешно, читатель будет указывать на токен сразу после конечного события.

Из вашего примера видно, что вызов unmarshal начинается с события START_ELEMENT, поэтому, когда вызов будет выполнен, reader будет на следующем событии после STOP_ELEMENT, что может быть START_ELEMENT из следующих <result>.

В этот момент ваш цикл while выполняется, обнаруживает, что в считывателе все еще есть события, поэтому вмешивается и вызывает xsr.next(), что оставляет ваш синтаксический анализатор на START_ELEMENT из <name>, который не проходит ваш тест if.

Таким образом, ваш код не работает, потому что вы случайно «пропускаете» открытие второго тега <result>. (Если я прав, ваш код должен фактически пропустить один из двух экземпляров <result>).

person GPI    schedule 10.03.2015
comment
Это имеет смысл, вы были правы. Спасибо большое - person CodyK; 10.03.2015
comment
В зависимости от вашего фактического входного XML ваш код мог работать (если синтаксический анализатор сообщал о пробелах как об отдельных событиях XML, ваш код мог работать, что действительно затрудняло отслеживание ошибки). - person GPI; 10.03.2015
comment
Да, я видел, как это может быть. Я чуть не рвал на себе волосы, спасибо. - person CodyK; 10.03.2015