java - 使用StAX读取XML字符串

  显示原文与译文双语对照的内容

我首次使用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);
 }
 }
}

我把手表放在"事件"和"。getElementText 。( ) 上"。 当代码停止时


String element = reader.getLocalName();

"。getElementText 。( )"值被显示,但一旦它从该行离开,就无法对它的求值。 当代码停止时:


status = reader.getElementText();

"元素"表显示正确的值。 finally,当我单步执行代码时,会捕捉到这里异常:


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

时间: 作者:

我找到了一个使用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的解决方案。

作者:

确保你读取了Stax的javadoc: 由于它是完全流解析模式,仅包含当前事件所包含的信息。 但是有一些例外,例如 getElementText() 必须从START_ELEMENT开始,但是将尝试从当前元素中合并所有文本标记;当返回时,它将指向匹配 END_ELEMENT 。

相反,START_ELEMENT上的getText() 不会返回任何在'开始/结束元素对) 里面有用的( 由于START_ELEMENT是指标记,而不是子文本标记/节点'。 如果你想使用它,你必须通过调用 streamReader.next(); 来显式地在流中移动游标,而 getElementText() 则为你。

那么是什么导致了? 使用完所有的启动/end-element对之后,下一个标记将是 END_ELEMENT ( 匹配父标记的任何内容) 。 所以你必须检查获得END_ELEMENT的情况,而不是另一个 START_ELEMENT 。

作者:

我遇到了类似的问题,因为我得到"illegalstateexception: 当我查看你的代码时,不是文本事件"我认为如果你有条件:


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

( 请注意:StaXMan在他的回答中指出了这一点) !

由于提取文本,XMLStreamReader实例必须遇到'。XMLStreamConstants 。字符'事件 !

也许有更好的方法来做这个。但是这是个快速而又肮脏的修复 我只显示了可能感兴趣的代码行 ) 要使这种情况发生,请稍微修改你的代码:


//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;

 } 

}

希望有帮助!

作者:

下面是一个带有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);
}

作者:
...