Jsoup: выбор HTML между разными классами

Я пытаюсь сделать что-то похожее на: Jsoup: Как получить весь html между двумя тегами заголовка

Однако, похоже, мой код избегает простого текста. Сайт, который я разбираю, имеет настройку кода таким образом:

div class = "quoted-message"
     Response. Can contain images, text, etc.
div class = "quoted-message"
     Another response to another quoted message

Фрагмент кода, используемый для обработки фактических сообщений:

Element quote = msg.select(".quoted-message").first();
Boolean hasQuote = false;
Elements siblings = null;
siblings = quote.siblingElements();
createQuotePost(quote);
List<Element> elementsBetween = new ArrayList<Element>();
    for (int i = 1; i < siblings.size(); i++) {
        Element sibling = siblings.get(i);
        if (! "div.quoted-message".equals(sibling.tagName())) {
            elementsBetween.add(sibling);
            }

        else {
            Log.v("location", "Clear and Process");
            processElementsBetween(elementsBetween);
            elementsBetween.clear();
        }
    }
    if (! elementsBetween.isEmpty())
        processElementsBetween(elementsBetween);

Однако это, похоже, не работает так, как я хочу. Ответы на код не имеют специального форматирования (т.е. находятся в теге p). Используя небольшое ведение журнала, я вижу, что они не помещаются в братьев и сестер Elements. Братья и сестры, кажется, просто включают разрывы строк и тому подобное.

Примечание. Я проверял это только на небольших сообщениях (простых вкладышах), чтобы сэкономить на просеивании длинных страниц распечаток.

Любые предложения о том, что делать?

РЕДАКТИРОВАТЬ: Вот фрагмент кода HTML между двумя кавычками div:

    MESSAGE TO BE QUOTED
    </div>
    <br />
    <br />
    Hello quoted message
    <br />
    I am a response
    <br />
    <br />
    <div class="quoted-message">

person intelacer    schedule 09.09.2011    source источник


Ответы (1)


Подумайте, что одна из проблем заключается в том, что вы запрашиваете элементы, а не узлы. Текстовые узлы являются узлами, а не элементами.

Попробуй это:

package grimbo.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;

public class StackOverflow {
    public static void main(String[] args) {
        String html = "<div class=quoted-message>message-1</div>\n    <br />\n    <br />\n    Hello quoted message\n    <br />\n    I am a response\n    <br />\n    <br />\n";
        html += "<div class=quoted-message>message-2</div>\n    <br />\n    <br />\n    Hello quoted message\n    <br />\n    I am a response\n    <br />\n    <br />\n";
        Document doc = Jsoup.parse(html);
        handleQuotedMessages(doc.select(".quoted-message"));
    }

    private static void handleQuotedMessages(Elements quotedMessages) {
        Element firstQuotedMessage = quotedMessages.first();
        List<Node> siblings = firstQuotedMessage.siblingNodes();
        List<Node> elementsBetween = new ArrayList<Node>();
        Element currentQuotedMessage = firstQuotedMessage;
        for (int i = 1; i < siblings.size(); i++) {
            Node sibling = siblings.get(i);

            // see if this Node is a quoted message
            if (!isQuotedMessage(sibling)) {
                elementsBetween.add(sibling);
            } else {
                createQuotePost(currentQuotedMessage, elementsBetween);
                currentQuotedMessage = (Element) sibling;
                elementsBetween.clear();
            }
        }
        if (!elementsBetween.isEmpty()) {
            createQuotePost(currentQuotedMessage, elementsBetween);
        }
    }

    private static boolean isQuotedMessage(Node node) {
        if (node instanceof Element) {
            Element el = (Element) node;
            return "div".equals(el.tagName()) && el.hasClass("quoted-message");
        }
        return false;
    }

    private static List<Element> filterElements(String tagName, List<Node> nodes) {
        List<Element> els = new ArrayList<Element>();
        for (Iterator<Node> it = nodes.iterator(); it.hasNext();) {
            Node n = it.next();
            if (n instanceof Element) {
                Element el = (Element) n;
                if (el.tagName().equals(tagName)) {
                    els.add(el);
                }
            }
        }
        return els;
    }

    private static void createQuotePost(Element quote, List<Node> elementsBetween) {
        System.out.println("createQuotePost: " + quote);
        System.out.println("createQuotePost: " + elementsBetween);
        List<Element> imgs = filterElements("img", elementsBetween);
        // handle imgs
    }
}
person Paul Grime    schedule 09.09.2011
comment
Однако работает отлично, есть ли простой способ вернуть узел в качестве элемента? Иногда он будет содержать изображения/ссылки, и у меня уже есть метод для их анализа, и я бы не хотел перекодировать все это. - person intelacer; 10.09.2011
comment
Итак, вы хотите сохранить только необработанные текстовые узлы в вашем списке elementsBetween? - person Paul Grime; 10.09.2011
comment
Итак, у меня есть метод (назовем его CreateMessage), для которого требуется элемент. Внутри метода я использую .select(img) для извлечения URL-адресов всех изображений в массив. Затем при отображении сообщения он использует этот список для возврата изображений. То же самое для URL-адресов и тому подобного. Если это большая проблема, я мог бы просто перекодировать ее, чтобы взять строку и отработать ее. - person intelacer; 10.09.2011
comment
Я думаю, что понял. Если <img> являются особыми, то в методе createQuotePost вы можете выполнить итерацию списка elementsBetween и специально обработать <img>. Проблема с использованием .select("img") заключается в том, что <img> не являются потомками цитируемого сообщения <div>, поэтому вам придется сделать что-то еще. Лично простой цикл elementsBetween был бы более чем адекватным (который я добавил к ответу). - person Paul Grime; 10.09.2011