使用 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);
}
}
}
我已将监视放在“event”和“reader.getElementText()”上。当代码在“reader.getElementText()”上停止时,
String element = reader.getLocalName();
会显示值,但一旦它离开该行,就无法对其进行求值。当代码停止于:
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();
}
}
I am using stax for the first time to parse an XML String. I have found some examples but can't get my code to work. This is the latest version of my code:
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);
}
}
}
I've put watches on "event" and "reader.getElementText()". When the code is stopped on
String element = reader.getLocalName();
the "reader.getElementText()" value is displayed, but as soon as it moves away from that line it can't be evaluated. When the code is stopped on:
status = reader.getElementText();
the "element" watch displays the correct value. Finally, when I step the code one more line, I catch this exception:
(com.ctc.wstx.exc.WstxParsingException) com.ctc.wstx.exc.WstxParsingException: Current state not START_ELEMENT
at [row,col {unknown-source}]: [1,29]
I've tried using status = reader.getText();
instead, but then I get this exception:
(java.lang.IllegalStateException) java.lang.IllegalStateException: Not a textual event (END_ELEMENT)
Can somebody point out what I'm doing wrong??
EDIT:
Adding JUnit code used to test:
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我找到了一个使用 XMLEventReader 而不是 XMLStreamReader 的解决方案:
我仍然有兴趣查看使用 XMLStreamReader 的解决方案。
I found a solution that uses XMLEventReader instead of XMLStreamReader:
I would still be interested in seeing a solution using XMLStreamReader.
请务必阅读 Stax 的 javadocs:由于它是完全流式解析模式,因此只有当前事件包含的信息可用。但也有一些例外;例如,getElementText() 必须从 START_ELEMENT 开始,但随后会尝试组合当前元素内的所有文本标记;返回时,它将指向匹配的END_ELEMENT。
相反,START_ELEMENT 上的 getText() 将不会返回任何有用的内容(因为 START_ELEMENT 引用标签,而不是“开始/结束元素对”内部的子文本标记/节点)。如果您想使用它,则必须通过调用streamReader.next();在流中显式移动光标。而 getElementText() 会为您完成此操作。
那么是什么原因导致了这个错误呢?消耗完所有开始/结束元素对后,下一个标记将是 END_ELEMENT (与父标记匹配)。因此,您必须检查是否获得了 END_ELEMENT,而不是另一个 START_ELEMENT。
Make sure you read javadocs for Stax: since it is fully streaming parsing mode, only information contained by the current event is available. There are some exceptions, however; getElementText() for example must start at START_ELEMENT, but will then try to combine all textual tokens from inside current element; and when returning, it will point to matching END_ELEMENT.
Conversely, getText() on START_ELEMENT will not returning anything useful (since START_ELEMENT refers to tag, not child text tokens/nodes 'inside' start/end element pair). If you want to use it instead, you have to explicitly move cursor in stream by calling streamReader.next(); whereas getElementText() does it for you.
So what is causing the error? After you have consumed all start/end-element pairs, next token will be END_ELEMENT (matching whatever was the parent tag). So you must check for the case where you get END_ELEMENT, instead of yet another START_ELEMENT.
当我收到“IllegalStateException:不是文本事件”消息时,我遇到了类似的问题
当我查看你的代码时,我发现如果你有一个条件:(
请注意:StaXMan 确实在他的答案中指出了这一点!)
这种情况发生是因为要获取文本,XMLStreamReader 实例必须遇到“XMLStreamConstants.CHARACTERS”事件!
也许有更好的方法来做到这一点......但这是一个快速而肮脏的修复(我只显示了可能感兴趣的代码行)
现在要实现这一点,请稍微修改您的代码:
希望有帮助!
I faced a similar issue as I was getting "IllegalStateException: Not a textual event" message
When I looked through your code I figured out that if you had a condition:
(Please note: StaXMan did point out this in his answer!)
This happens since to fetch text, XMLStreamReader instance must have encountered 'XMLStreamConstants.CHARACTERS' event!
There maybe a better way to do this...but this is a quick and dirty fix (I have only shown lines of code that may be of interest)
Now to make this happen modify your code slightly:
Hope that helps!
以下是 XMLStreamReader 的示例:
Here is an example with XMLStreamReader: