10

XML文字列を解析するために初めてstaxを使用しています。いくつかの例を見つけましたが、コードを動作させることができません。これは私のコードの最新バージョンです:

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();

「要素」ウォッチは正しい値を表示します。最後に、コードをもう 1 行実行すると、次の例外が発生します。

(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();
    }
}
4

4 に答える 4

9

XMLStreamReader の代わりに XMLEventReader を使用するソリューションを見つけました。

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 を使用したソリューションを見てみたいと思っています。

于 2011-01-11T16:49:22.933 に答える
5

Stax の javadoc を必ず読んでください。これは完全なストリーミング解析モードであるため、現在のイベントに含まれる情報のみが利用可能です。ただし、いくつかの例外があります。たとえば、getElementText() は START_ELEMENT で開始する必要がありますが、現在の要素内のすべてのテキスト トークンを結合しようとします。戻るときは、一致する END_ELEMENT を指します。

逆に、START_ELEMENT の getText() は有用なものを返しません (START_ELEMENT は、開始/終了要素ペアの「内側」の子テキスト トークン/ノードではなく、タグを参照するため)。代わりに使用する場合は、streamReader.next(); を呼び出して明示的にストリーム内でカーソルを移動する必要があります。一方、 getElementText() はそれを行います。

では、エラーの原因は何ですか? すべての開始要素と終了要素のペアを消費した後、次のトークンは END_ELEMENT になります (親タグと一致します)。したがって、さらに別の START_ELEMENT ではなく、END_ELEMENT を取得するケースを確認する必要があります。

于 2011-05-31T22:15:01.643 に答える
2

「IllegalStateException: Not a textual event」というメッセージが表示されたため、同様の問題に直面しました。コードを調べたところ、次の条件があることがわかりました。

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;

 }    

}

それが役立つことを願っています!

于 2011-08-11T21:11:23.403 に答える