#python #lxml #xml.etree
#python #lxml #xml.etree
Вопрос:
Я пытаюсь удалить все между, если между ними число 66:
Я получаю следующую ошибку: TypeError: аргумент типа ‘NoneType’ не может быть повторен … если element.tag == ‘answer’ и ‘-66’ в element.text:
Что в этом плохого? Любая помощь?
#!/usr/local/bin/python2.7
# -*- coding: UTF-8 -*-
from lxml import etree
planhtmlclear_utf=u"""
<questionaire>
<question>
<questiontext>What's up?</questiontext>
<answer></answer>
</question>
<question>
<questiontext>Cool?</questiontext>
<answer>-66</answer>
</question>
</questionaire>
"""
html = etree.fromstring(planhtmlclear_utf)
questions = html.xpath('/questionaire/question')
for question in questions:
for element in question.getchildren():
if element.tag == 'answer' and '-66' in element.text:
html.xpath('/questionaire')[0].remove(question)
print etree.tostring(html)
Ответ №1:
element.text, похоже, отсутствует на некоторых итерациях. Ошибка говорит о том, что он не может просмотреть None для «-66», поэтому сначала проверьте, что element.text не является None, например:
html = etree.fromstring(planhtmlclear_utf)
questions = html.xpath('/questionaire/question')
for question in questions:
for element in question.getchildren():
if element.tag == 'answer' and element.text and '-66' in element.text:
html.xpath('/questionaire')[0].remove(question)
print etree.tostring(html)
Строка, в которой он терпит неудачу в xml <answer></answer>
, — это место, где между тегом нет текста.
Редактировать (для второй части вашей проблемы об объединении тегов):
Вы можете использовать BeautifulSoup
так:
from lxml import etree
import BeautifulSoup
planhtmlclear_utf=u"""
<questionaire>
<question>
<questiontext>What's up?</questiontext>
<answer></answer>
</question>
<question>
<questiontext>Cool?</questiontext>
<answer>-66</answer>
</question>
</questionaire>"""
html = etree.fromstring(planhtmlclear_utf)
questions = html.xpath('/questionaire/question')
for question in questions:
for element in question.getchildren():
if element.tag == 'answer' and element.text and '-66' in element.text:
html.xpath('/questionaire')[0].remove(question)
soup = BeautifulSoup.BeautifulStoneSoup(etree.tostring(html))
print soup.prettify()
С принтами:
<questionaire>
<question>
<questiontext>
What's up?
</questiontext>
<answer>
</answer>
</question>
</questionaire>
Вот ссылка, по которой вы можете скачать модуль BeautifulSoup.
Или, чтобы сделать это более компактным способом:
from lxml import etree
import BeautifulSoup
# abbreviating to reduce answer length...
planhtmlclear_utf=u"<questionaire>.........</questionaire>"
html = etree.fromstring(planhtmlclear_utf)
[question.getparent().remove(question) for question in html.xpath('/questionaire/question[answer/text()="-66"]')]
print BeautifulSoup.BeautifulStoneSoup(etree.tostring(html)).prettify()
Комментарии:
1. Может быть, вы можете помочь мне сделать еще один шаг: -P Теперь я получаю вывод: <вопросник> <вопрос> <текст вопроса> Что случилось? </questiontext> <ответ /> </question> </questionaire> ……. так что ответ показан не полностью… почему это так?
Ответ №2:
Альтернативой проверке, если element.text
есть None
, является уточнение вашего XPath:
questions = html.xpath('/questionaire/question[answer/text()="-66"]')
for question in questions:
question.getparent().remove(question)
Скобки [...]
означают «такое, что». Итак
question # find all question elements
[ # such that
answer # it has an answer subelement
/text() # whose text
= # equals
"-66" # "-66"
]
Комментарии:
1. это решает проблему, заключающуюся в том, что он не касается других элементов ответа… в приведенном выше примере я получаю вырезанные элементы ответа … но я не знаю почему… в любом случае с этим решением это работает!
2. нет, извините … он вырезает пустые теги ответов… почему это всегда происходит?
3. Я не уверен, что понимаю вопрос. Вы имеете
<answer></answer>
в виду, сокращается до<answer/>
? Все в порядке; они эквивалентны.4. Да .. это то, что я имел в виду… но что я могу сделать, чтобы предотвратить это? Потому что мне нужны теги для правильного форматирования ..? Большое спасибо!
5.
import lxml.html as lh
. Затемlh.tostring(html)
.