Groovy XmlParser/XmlSlurper: позиция node.localText()?

У меня есть дополнительный вопрос по этому вопросу: Groovy XmlSlurper получает значение узла без дочерних элементов.

Это объясняет, что для того, чтобы получить локальный внутренний текст узла (HTML) без рекурсивного получения вложенного текста потенциальных внутренних дочерних узлов, нужно использовать #localText() вместо #text().

Например, немного расширенный пример из исходного вопроса:

<html>
    <body>
        <div>
            Text I would like to get1.
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </div>
        <span>
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </span>
    </body>
</html>

с нанесенным раствором:

def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlSlurper(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)

println htmlParsed.body.div[0].localText()[0]

вернется:

[Text I would like to get1., Text I would like to get2., Text I would like to get3.]

Однако при разборе части <span> в этом примере

println htmlParsed.body.span[0].localText()

вывод

[Text I would like to get2., Text I would like to get3.]

Проблема, с которой я столкнулся сейчас, заключается в том, что, по-видимому, невозможно точно определить местоположение («между дочерними узлами») текстов. Я ожидал, что второй вызов даст

[, Text I would like to get2., Text I would like to get3.]

Это прояснило бы: позиция 0 (перед дочерним элементом 0) пуста, позиция 1 (между дочерними элементами 0 и 1) — «Текст, который я хотел бы получить2», а позиция 2 (между дочерними элементами 1 и 2) — «Текст». Я хотел бы получить 3». Но, учитывая, что API работает так, как он работает, по-видимому, нет способа определить, действительно ли текст, возвращаемый по индексу 0, расположен по индексу 0 или по любому другому индексу, и то же самое верно для всех других индексов.

Я пробовал это как с XmlSlurper, так и с XmlParser, что дало одинаковые результаты.

Если я не ошибаюсь, как следствие, также невозможно полностью воссоздать исходный HTML-документ, используя информацию из синтаксического анализатора, потому что эта информация «текстового индекса» теряется.

Мой вопрос: есть ли способ узнать эти текстовые позиции? Ответ, требующий от меня изменить синтаксический анализатор, также будет приемлемым.


ОБНОВЛЕНИЕ/РЕШЕНИЕ:

Для дальнейшего справки, вот ответ Уилла П, примененный к исходному коду:

def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlParser(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)

println htmlParsed.body.div[0].children().collect {it in String ? it : null}

Это дает:

[Text I would like to get1., null, Text I would like to get2., null, Text I would like to get3.]

Нужно использовать XmlParser вместо XmlSlurper с node.children().


person SputNick    schedule 12.09.2015    source источник


Ответы (1)


Я не знаю jsoup, и я надеюсь, что это не мешает решению, но с чистым XmlParser вы можете получить массив children(), который содержит необработанную строку:

html = '''<html>
    <body>
        <div>
            Text I would like to get1.
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </div>
        <span>
            <a href="http://intro.com">extra stuff</a>
            Text I would like to get2.
            <a href="http://example.com">link to example</a>
            Text I would like to get3.
        </span>
    </body>
</html>'''

def root = new XmlParser().parseText html

root.body.div[0].children().with {
    assert get(0).trim() == 'Text I would like to get1.'
    assert get(0).getClass() == String

    assert get(1).name() == 'a'
    assert get(1).getClass() == Node

    assert get(2) == '''
            Text I would like to get2.
            '''
}
person Will    schedule 14.09.2015
comment
Вот и все! Судя по всему, он работает только с XmlParser, а не с XmlSlurper. Спасибо. Я обновлю свой вопрос с решением. Я только хочу, чтобы Groovy более четко документировал различия между этими двумя классами... - person SputNick; 14.09.2015