Java SAX DefaultHandler 解析获取具有多个同名标签的标签值
Java SAX DefaultHandler parsing get tag value with several tags with the same name
我有这个输入 XML:
<REQUEST>
<ELEMENT>element inside request</ELEMENT>
<NUMBER>250</NUMBER>
<LIST>
<ELEMENT>element inside list</ELEMENT>
<LETTER>A</LETTER>
</LIST>
<OTHER1>other 1</OTHER1>
</REQUEST>
我正在 class 中扩展 DefaultHandler,我用它来获取值。
这是我的 class:
public class MyHandler extends DefaultHandler {
private String elementName = null;
private boolean bElement = false;
private String element = null;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (bElement){
elementName = new String(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if("ELEMENT".equalsIgnoreCase(qName) && elementName == null){
element = elementName;
}
bElement = false;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("ELEMENT")){
bElement = true;
}
}
public String getElement() {
return this.element;
}
}
我有这个逻辑来获取元素值(请求是一个 HttpServletRequest):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while ((n = request.getInputStream().read(buf)) >= 0) {
baos.write(buf, 0, n);
}
byte[] content = baos.toByteArray();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
MyHandler handler = new MyHandler();
saxParser.parse(new ByteArrayInputStream(content), handler);
return handler.getElement();
当我发送上面的XML时,我们得到了REQUEST->LIST->ELEMENT里面的值,所以我得到了String:
element inside list
但我想先获取里面的字符串 ELEMENT 标签
element inside request
我需要完成 MyHandler class 中的代码以获取 中的 ELEMENT 值REQUEST->ELEMENT 并且没有得到另一个 ELEMENT.
您需要跟踪 XML 中的完整位置。
注意 - 这是完全未经测试的代码。
public class MyHandler extends DefaultHandler {
// Use a DEQUE to track the current position inthe xml.
private Deque<String> position = new ArrayDeque<>();
// My data.
private StringBuilder data = new StringBuilder();
private String element = null;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (match()) {
// Append to my buffer.
data.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// Ending a tag - pop it from end.
position.removeLast();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// Starting a tag - push it at the end.
position.addLast(qName);
}
public String getElement() {
return this.element;
}
// Specifically looking for the REQUEST.ELEMENT - not the REQUEST.LIST.ELEMENT
private final String[] lookingFor = {"REQUEST", "ELEMENT"};
private boolean match() {
// Must be that deep.
if (position.size() == lookingFor.length) {
// Must match.
Iterator<String> match = position.iterator();
for (int i = 0; i < lookingFor.length; i++) {
// Match?
if (!match.next().equals(lookingFor[i])) {
return false;
}
}
} else {
// Wrong depth.
return false;
}
// No mismatch -> match!
return true;
}
}
此外 - 顺便说一句,当调用 characters
时,您应该始终 append。
我有这个输入 XML:
<REQUEST>
<ELEMENT>element inside request</ELEMENT>
<NUMBER>250</NUMBER>
<LIST>
<ELEMENT>element inside list</ELEMENT>
<LETTER>A</LETTER>
</LIST>
<OTHER1>other 1</OTHER1>
</REQUEST>
我正在 class 中扩展 DefaultHandler,我用它来获取值。
这是我的 class:
public class MyHandler extends DefaultHandler {
private String elementName = null;
private boolean bElement = false;
private String element = null;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (bElement){
elementName = new String(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if("ELEMENT".equalsIgnoreCase(qName) && elementName == null){
element = elementName;
}
bElement = false;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("ELEMENT")){
bElement = true;
}
}
public String getElement() {
return this.element;
}
}
我有这个逻辑来获取元素值(请求是一个 HttpServletRequest):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while ((n = request.getInputStream().read(buf)) >= 0) {
baos.write(buf, 0, n);
}
byte[] content = baos.toByteArray();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
MyHandler handler = new MyHandler();
saxParser.parse(new ByteArrayInputStream(content), handler);
return handler.getElement();
当我发送上面的XML时,我们得到了REQUEST->LIST->ELEMENT里面的值,所以我得到了String:
element inside list
但我想先获取里面的字符串 ELEMENT 标签
element inside request
我需要完成 MyHandler class 中的代码以获取 中的 ELEMENT 值REQUEST->ELEMENT 并且没有得到另一个 ELEMENT.
您需要跟踪 XML 中的完整位置。
注意 - 这是完全未经测试的代码。
public class MyHandler extends DefaultHandler {
// Use a DEQUE to track the current position inthe xml.
private Deque<String> position = new ArrayDeque<>();
// My data.
private StringBuilder data = new StringBuilder();
private String element = null;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (match()) {
// Append to my buffer.
data.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// Ending a tag - pop it from end.
position.removeLast();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// Starting a tag - push it at the end.
position.addLast(qName);
}
public String getElement() {
return this.element;
}
// Specifically looking for the REQUEST.ELEMENT - not the REQUEST.LIST.ELEMENT
private final String[] lookingFor = {"REQUEST", "ELEMENT"};
private boolean match() {
// Must be that deep.
if (position.size() == lookingFor.length) {
// Must match.
Iterator<String> match = position.iterator();
for (int i = 0; i < lookingFor.length; i++) {
// Match?
if (!match.next().equals(lookingFor[i])) {
return false;
}
}
} else {
// Wrong depth.
return false;
}
// No mismatch -> match!
return true;
}
}
此外 - 顺便说一句,当调用 characters
时,您应该始终 append。