Обратный анализ дочернего элемента XML в виде строки

Я пытаюсь проанализировать сложный XML, и xpath ведет себя не так, как я думал. Вот мой образец xml:

<project>
    <samples>
        <sample>show my balance</sample>
        <sample>show me the <subsample value='USD'>money</subsample>today</sample>
    </samples>
</project>

Вот мой код на питоне:

from lxml import etree

somenode="<project><samples><sample>show my balance</sample><sample>show me the <subsample value='USD'>money</subsample>today</sample></samples></project>"

somenode_etree = etree.fromstring(somenode)

for x in somenode_etree.iterfind(".//sample"):
    print (etree.tostring(x))

Я получаю вывод:

b'<sample>show my balance</sample><sample>show me the <subsample value="USD">money</subsample>today</sample></samples></project>'
b'<sample>show me the <subsample value="USD">money</subsample>today</sample></samples></project>'

когда я ожидал:

show my balance
show me the <subsample value="USD">money</subsample>today

Что я делаю не так?

Какой результат вы хотите вернуть? Текст или XML? Трудно и немного странно хотеть и то, и другое. И странно может указывать XY-проблема. Пожалуйста, опишите вашу общую проблему и цель.

Parfait 23.04.2022 16:56

Я хочу, чтобы что-то между тегами <sample></sample> возвращалось в виде строки для обработки в другом формате данных. LMC подтвердил, что ошибочный вывод был вызван ошибкой, и в противном случае мой код даст мне ожидаемый результат.

C. L. 24.04.2022 04:45
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
2
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этот XPath получит текст и элементы, как и ожидалось.

result = somenode_etree.xpath(".//sample/text() | .//sample/*")
result
['show my balance', 'show me the ', <Element subsample at 0x7f0516cfa288>, 'today']

Печать найденных узлов по запросу OP

for x in somenode_etree.xpath(".//sample/text() | .//sample/*[node()]"):
    if type(x) == etree._Element:
        print(etree.tostring(x, method='xml',with_tail=False).decode('UTF-8'))
    else:
        print(x)

Результат

show my balance
show me the 
<subsample value="USD">money</subsample>
today

with_tail аргумент предотвращает добавление хвостового текста к элементу.

Или

>>> for x in somenode_etree.xpath(".//sample/text() | .//sample/*"):
...     if type(x) == etree._Element:
...         print(x.text)
...     else:
...         print(x)
... 
show my balance
show me the 
money
today

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

C. L. 23.04.2022 01:35

Конечно. Хорошее упражнение для вас ;-)

LMC 23.04.2022 01:49

Я пытаюсь понять, почему код, который я вставил в вопрос, не дает ожидаемого ответа. Я попробовал то же выражение xpath в онлайн-тестере (freeformatter.com/xpath-tester.html#ad-output) и получил ожидаемый результат. Я также пробовал его на ноутбуке с более старой версией python/lxml от 2021 года, и там он тоже работает. Однако этот код не работает при новой установке Anaconda. Я пытаюсь понять, что изменилось и как это обойти.

C. L. 23.04.2022 01:56

Вы получаете элементы sample, а не их потомков.

LMC 23.04.2022 02:20

@К.Л. Обновлен ответ для печати результата, как вы ожидали. Похоже, в lxml есть ошибка.

LMC 23.04.2022 18:24

Удивительно! Спасибо, что подтвердили, что это ошибка.

C. L. 24.04.2022 04:43

@К.Л. не ошибка лол. Обновил мой ответ правильным вариантом tostring(). В любом случае это странно, я не знаю ни одной реализации tails текста в элемент при печати (java, xmllint).

LMC 27.04.2022 20:43

да, я видел это в отчете об ошибке. Я понимаю, что вы предоставили альтернативное решение, но знаете ли вы, почему я не могу просто использовать XPATH ".//sample", чтобы получить то, что мне нужно. Раньше это работало, а теперь нет, и я не могу понять, какая версия реализовала изменение, которое сломало это. Любой онлайн-тестер XPATH показывает мой ожидаемый ответ, но lxml, кажется, делает это по-другому.

C. L. 28.04.2022 21:24

Другие вопросы по теме