Вот пример с XMLStreamReader:

ользую Stax в первый раз для анализа строки XML. Я нашел несколько примеров, но не могу заставить мой код работать. Это последняя версия моего кода:

public class AddressResponseParser
{
    private static final String STATUS = "status";
    private static final String ADDRESS_ID = "address_id";
    private static final String CIVIC_ADDRESS = "civic_address";

    String status = null;
    String addressId = null;
    String civicAddress = null;

    public static AddressResponse parseAddressResponse(String response)
    {

        try
        {
            byte[] byteArray = response.getBytes("UTF-8");
            ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream);

            while (reader.hasNext())
            {
                int event = reader.next();

                if (event == XMLStreamConstants.START_ELEMENT)
                {
                    String element = reader.getLocalName();

                    if (element.equals(STATUS))
                    {
                        status = reader.getElementText();
                        continue;
                    }

                    if (element.equals(ADDRESS_ID))
                    {
                        addressId = reader.getText();
                        continue;
                    }

                    if (element.equals(CIVIC_ADDRESS))
                    {
                        civicAddress = reader.getText();
                        continue;
                    }
                }
            }
        }
        catch (Exception e)
        {
            log.error("Couldn't parse AddressResponse", e);
        }
    }
}

Я поставил часы на «событие» и «reader.getElementText ()». Когда код остановлен на

String element = reader.getLocalName();

отображается значение «reader.getElementText ()», но, как только оно удаляется от этой строки, оно не может быть оценено. Когда код остановлен:

status = reader.getElementText();

Часы «Элемент» отображают правильное значение. Наконец, когда я перешагиваю код еще на одну строку, я ловлю это исключение:

(com.ctc.wstx.exc.WstxParsingException) com.ctc.wstx.exc.WstxParsingException: Current state not START_ELEMENT
 at [row,col {unknown-source}]: [1,29]

Я пытался использоватьstatus = reader.getText(); вместо этого, но тогда я получаю это исключение:

(java.lang.IllegalStateException) java.lang.IllegalStateException: Not a textual event (END_ELEMENT)

Может кто-нибудь указать, что я делаю не так ??

РЕДАКТИРОВАТЬ:

Добавление кода JUnit, используемого для тестирования:

public class AddressResponseParserTest
{
    private String status = "OK";
    private String address_id = "123456";
    private String civic_address = "727";

    @Test
    public void testAddressResponseParser() throws UnsupportedEncodingException, XMLStreamException
    {
        AddressResponse parsedResponse = AddressResponseParser.parseAddressResponse(this.responseXML());

        assertEquals(this.status, parsedResponse.getStatus());

        assertEquals(this.address_id, parsedResponse.getAddress()
                .getAddressId());
        assertEquals(this.civic_address, parsedResponse.getAddress()
                .getCivicAddress());
    }

    private String responseXML()
    {
        StringBuffer buffer = new StringBuffer();

        buffer.append("<response>");
        buffer.append("<status>OK</status>");
        buffer.append("<address>");
        buffer.append("<address_id>123456</address_id>");
        buffer.append("<civic_address>727</civic_address>");
        buffer.append("</address>");
        buffer.append("</response>");

        return buffer.toString();
    }
}
 peter.murray.rust11 янв. 2011 г., 00:07
Мой личный подход заключается в том, чтобы найти учебник по stAX и убедиться, что он работает для меня, а затем расширить его, чтобы он соответствовал вашим требованиям. Я отмечаю, что вы ловите только START_ELEMENT - я бы добавил} else { пункт, который регистрирует другие события. Это скажет вам, как далеко вы прошли через данные.
 peter.murray.rust10 янв. 2011 г., 23:55
Как выглядят ваши XML-данные? Вы уверены, что это правильно сформировано? (Возможно, покажите нам небольшое количество)
 sdoca11 янв. 2011 г., 00:00
XML - это строковый ответ от другого класса / метода, который будет вызывать мой код. Я пишу JUnit для тестирования парсера. Я добавил код JUnit к вопросу, включая метод, который генерирует XML для теста.

Ответы на вопрос(4)

так как это полностью потоковый режим анализа, доступна только информация, содержащаяся в текущем событии. Однако есть некоторые исключения; Например, getElementText () должен начинаться с START_ELEMENT, но затем попытается объединить все текстовые токены изнутри текущего элемента; и при возврате он будет указывать на соответствие END_ELEMENT.

И наоборот, getText () в START_ELEMENT не вернет ничего полезного (поскольку START_ELEMENT относится к тегу, а не к дочерним текстовым токенам / узлам «внутри» пары начала / конца элемента). Если вы хотите использовать его вместо этого, вы должны явно перемещать курсор в потоке, вызывая streamReader.next (); тогда как getElementText () сделает это за вас.

Так что же вызывает ошибку? После того, как вы использовали все пары начальный / конечный элемент, следующим токеном будет END_ELEMENT (совпадающий с тем, который был родительским тегом). Таким образом, вы должны проверить случай, когда вы получите END_ELEMENT, а не еще один START_ELEMENT.

 Boris Treukhov20 июн. 2013 г., 15:17
+1 Этот ответ кажется правильным.

когда получал сообщение «IllegalStateException: не текстовое событие». Когда я просматривал ваш код, я понял, что если у вас есть условие:

if (event == XMLStreamConstants.START_ELEMENT){
....
addressId = reader.getText(); // it throws exception here
....
}

(Обратите внимание: StaXMan указал на это в своем ответе!)

Это происходит потому, что при извлечении текста экземпляр XMLStreamReader должен встретиться с событием «XMLStreamConstants.CHARACTERS»!

Возможно, есть лучший способ сделать это ... но это быстрое и грязное исправление (Я только показал строки кода, которые могут представлять интересТеперь, чтобы это произошло, немного измените ваш код:

// this will tell the XMLStreamReader that it is appropriate to read the text
boolean pickupText = false

while(reader.hasNext()){

if (event == XMLStreamConstants.START_ELEMENT){
   if( (reader.getLocalName().equals(STATUS) )
   || ( (reader.getLocalName().equals(STATUS) )
   || ((reader.getLocalName().equals(STATUS) ))
         // indicate the reader that it has to pick text soon!
     pickupText = true;
   }
}else if (event == XMLStreamConstants.CHARACTERS){
  String textFromXML = reader.getText();
  // process textFromXML ...

  //...

  //set pickUpText false
  pickupText = false;

 }    

}

Надеюсь, это поможет!

Решение Вопроса

которое использует XMLEventReader вместо XMLStreamReader:

public MyObject parseXML(String xml)
    throws XMLStreamException, UnsupportedEncodingException
{
    byte[] byteArray = xml.getBytes("UTF-8");
    ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
    XMLInputFactory inputFactory = XMLInputFactory.newInstance();
    XMLEventReader reader = inputFactory.createXMLEventReader(inputStream);

    MyObject object = new MyObject();

    while (reader.hasNext())
    {
        XMLEvent event = (XMLEvent) reader.next();

        if (event.isStartElement())
        {
            StartElement element = event.asStartElement();

            if (element.getName().getLocalPart().equals("ElementOne"))
            {
                event = (XMLEvent) reader.next();

                if (event.isCharacters())
                {
                     String elementOne = event.asCharacters().getData();
                     object.setElementOne(elementOne);
                }
                continue;
            }
            if (element.getName().getLocalPart().equals("ElementTwo"))
            {
                event = (XMLEvent) reader.next();
                if (event.isCharacters())
                {
                     String elementTwo = event.asCharacters().getData();
                     object.setElementTwo(elementTwo);
                }
                continue;
            }
        }
    }

    return object;
}

Мне все еще было бы интересно увидеть решение, использующее XMLStreamReader.

   XMLInputFactory inputFactory = XMLInputFactory.newInstance();

try {
   XMLStreamReader xmlReader = inputFactory.createXMLStreamReader(file);
   String elementValue = "";

   while (xmlReader.hasNext()) {
      int xmlEventType = xmlReader.next();

      switch (xmlEventType) {  
          // Check for Start Elements
          case XMLStreamConstants.START_ELEMENT:

              //Get current Element Name
              String elementName = xmlReader.getLocalName();

              if(elementName.equals("td")) {
              //Get Elements Value
              elementValue = xmlReader.getElementText();
              }

              //Add the new Start Element to the Map
              elements.put(elementName, elementValue);                
              break;
          default:
             break;
          }    
   }
   //Close Session
   xmlReader.close();        
} catch (Exception e) {
    log.error(e.getMessage(), e);
}

Ваш ответ на вопрос