我第一次使用stax来解析XML String。我找到了一些例子,但无法让我的代码工作。这是我的代码的最新版本:
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);
}
}
}
我把手表放在“event”和“reader.getElementText()”上。代码停止时
String element = reader.getLocalName();
显示“reader.getElementText()”值,但一旦离开该行,就无法对其进行评估。当代码停止时:
status = reader.getElementText();
“element”手表显示正确的值。最后,当我再一步执行代码时,我发现了这个异常:
(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();
}
}
答案 0 :(得分:9)
我找到了一个使用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的解决方案。
答案 1 :(得分:4)
确保您读取了Stax的javadoc:由于它是完全流式解析模式,因此只有当前事件包含的信息可用。但是有一些例外;例如,getElementText()必须从START_ELEMENT开始,但是会尝试从当前元素内部组合所有文本标记;返回时,它将指向匹配END_ELEMENT。
相反,START_ELEMENT上的getText()不会返回任何有用的内容(因为START_ELEMENT引用标记,而不是'start / end元素对内的子文本标记/节点')。如果要使用它,则必须通过调用streamReader.next()在流中显式移动游标;而getElementText()为你做。
那么导致错误的原因是什么?在使用了所有开始/结束元素对之后,下一个标记将是END_ELEMENT(匹配父标记的任何内容)。因此,您必须检查END_ELEMENT的情况,而不是另一个START_ELEMENT。
答案 2 :(得分: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;
}
}
希望有所帮助!
答案 3 :(得分:0)
以下是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);
}