【发布时间】:2011-11-29 07:39:52
【问题描述】:
我有一个包含 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
但我需要使用 SAX 或 DOM 或 ... 在 Java 中实现它?
我在这篇文章中找到了一个使用 SAX 的解决方案:SAX Parser : Retrieving HTML tags from XML,但它有很多错误,并且不适用于大量 XML 数据。
更新:
我的 SAX 实现: 在某些情况下,它会抛出异常:java.lang.StringIndexOutOfBoundsException: String index out of range: -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;
}
}
更新 2:(使用 StringBuilder)
我是这样通过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>
更新 3:
我终于实现了解析器处理程序:
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;
}
}
【问题讨论】:
-
您需要更好地定义输入 XML,特别是尽可能地定义所需的输出,因为您的帖子根本不清楚。您似乎希望保留一些标签,但其他标签不保留。此外,如果 XML 非常大,则 DOM 可能不可行,因为 DOM 要求在执行分析之前加载整个文档模型。其他选项是 SAX 和 StAX。
-
感谢您编辑我糟糕的文章。是的,我需要获取
标签的内容。我用我的 SAX 实现更新了我的帖子,但在某些情况下它不起作用。你能帮我解决我更新的问题吗?
标签: java xml dom xml-parsing sax