我有一个包含HTML标记的XML文档:
<chapter>
<h1>title of content</h1>
<p> my paragraph ... </p>
</chapter>
我需要获取<chapter>
标记的内容,我的输出将是:
<h1>title of content</h1>
<p> my paragraph ... </p>
我的问题类似于这篇文章:How parse XML to get one tag and save another tag inside
但我需要在Java中使用SAX或DOM或......?
来实现它我在这篇文章中找到了一个使用SAX的解决方案:SAX Parser : Retrieving HTML tags from XML但它非常错误,并且无法处理大量的XML数据。
我的SAX实施: 在某些情况下,它会抛出异常:java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:-4029
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private char[] temp;
String insideTag;
private int startPosition;
private int endPosition;
private String tag;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
tagFlag = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
insideTag = new String(temp, startPosition, endPosition - startPosition);
tagFlag = false;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {
temp = ch;
if (tagFlag) {
startPosition = start;
tagFlag = false;
}
endPosition = start + length;
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
我通过StringBuilder以这种方式累积了字符:
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private char[] temp;
String insideTag;
private String tag;
private StringBuilder builder;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
builder = new StringBuilder();
tagFlag = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
insideTag = builder.toString();
tagFlag = false;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {
if (tagFlag) {
builder.append(ch, start, length);
}
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
但builder.append(ch, start, length);
不会在缓冲区中添加<EmbeddedTag atr="...">
和</EmbeddedTag>
等开始标记。本代码打印输出:
title of content
my paragraph ...
而不是预期的输出:
<h1>title of content</h1>
<p> my paragraph ... </p>
最后我实现了解析器处理程序:
public class MyXMLHandler extends DefaultHandler {
private boolean tagFlag = false;
private String insideTag;
private String tag;
private StringBuilder builder;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(tag)) {
builder = new StringBuilder();
tagFlag = true;
}
if (tagFlag) {
builder.append("<" + qName);
for (int i = 0; i < attributes.getLength(); i++) {
builder.append(" " + attributes.getLocalName(i) + "=\"" +
attributes.getValue(i) + "\"");
}
builder.append(">");
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (tagFlag) {
builder.append("</" + qName + ">");
}
if (qName.equalsIgnoreCase(tag)) {
insideTag = builder.toString();
tagFlag = false;
}
System.out.println("End Element :" + qName);
}
public void characters(char ch[], int start, int length)
throws SAXException {
temp = ch;
if (tagFlag) {
builder.append(ch, start, length);
}
}
public String getInsideTag(String tag) {
this.tag = tag;
return insideTag;
}
}
答案 0 :(得分:0)
您的代码的问题在于您尝试记住通过characters
方法传递给您的字符串的开始和结束位置。在抛出的异常中看到的是内部标记的结果,该标记在字符缓冲区的末尾附近开始,并在下一个字符缓冲区的开头附近结束。
使用sax时,您需要在提供字符时复制它们,或者在您需要时可以清除它们占用的临时缓冲区。
最好的办法是不要记住缓冲区中的位置,而是要在StringBuilder
中创建一个新的startElement
并添加字符,然后在{{{{}}中获取完整的字符串。 1}}。
答案 1 :(得分:0)