У меня есть документ XML с тегами HTML:
<chapter>
<h1>title of content</h1>
<p> my paragraph ... </p>
</chapter>
Мне нужно получить содержимое тега <chapter>
, и мой вывод будет:
<h1>title of content</h1>
<p> my paragraph ... </p>
Мой вопрос похож на этот пост: Как разобрать XML, чтобы получить один тег и сохранить другой тег внутри
Но мне нужно реализовать это на Java, используя SAX или DOM или ...?
Я нашел солутон с использованием SAX в этом посте: SAX Parser: извлечение тегов HTML из 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;
}
}
Обновление 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;
}
}