Как получить содержимое <tagname>, которое содержит другой встроенный тег XML в Java? - PullRequest
0 голосов
/ 02 октября 2011

У меня есть документ 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;
}

}

Ответы [ 2 ]

0 голосов
/ 02 октября 2011

Попробуйте использовать Digester , я использовал его несколько лет назад, версию 1.5, и это было просто для создания карт для xml, как вы. Просто статья о том, как использовать Digester, но это для версии 1.5, и в настоящее время есть 3.0. Я думаю, что последняя версия содержит много новых функций ...

0 голосов
/ 02 октября 2011

Проблема с вашим кодом заключается в том, что вы пытаетесь запомнить начальную и конечную позиции строки, переданной вам с помощью метода characters. То, что вы видите в генерируемом исключении, является результатом внутреннего тега, который начинается около конца символьного буфера и заканчивается около начала следующего символьного буфера.

С помощью sax вам нужно копировать символы, когда они предлагаются, или временный буфер, который они занимают, может быть очищен, когда они вам нужны.

Лучше всего не запоминать позиции в буферах, а создать новую StringBuilder в startElement и добавить к ней символы, а затем вывести полную строку из строителя в endElement.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...