BeautifulSoup/LXML.html : удалить тег и его дочерние элементы, если дочерний элемент выглядит как x

#python #beautifulsoup #lxml

#python #beautifulsoup #lxml

Вопрос:

У меня проблема с поиском правильного решения. Я хочу удалить <question> и его дочерние элементы, если <answer> равно = 99. В результате мне нужна строка с отфильтрованными вопросами. У меня есть следующая структура html:

 <html>
 <body>        
  <questionaire>
   <question>
    <questiontext>
     Do I have a question?
    </questiontext>
    <answer>
     99
    </answer>
   </question>
   <question>
    <questiontext>
     Do I love HTML/XML parsing?
    </questiontext>
    <questalter>
     <choice>
      1 oh god yeah
     </choice>
     <choice>
      2 that makes me feel good
     </choice>
     <choice>
      3 oh hmm noo
     </choice>
     <choice>
      4 totally
     </choice>
     </questalter>
     <answer>
      4
    </answer>
   </question>
   <question>
  </questionaire>
 </body>
</html>      
  

До сих пор я пытался реализовать это с помощью xpath … но lxml.html не имеет iterparse … не так ли? Спасибо!

Ответ №1:

Это сделает именно то, что вам нужно:

 from xml.dom import minidom

doc = minidom.parseString(text)
for question in doc.getElementsByTagName('question'):
    for answer in question.getElementsByTagName('answer'):
        if answer.childNodes[0].nodeValue.strip() == '99':
            question.parentNode.removeChild(question)

print doc.toxml()
  

Результат:

 <html>
 <body>        
  <questionaire>

   <question>
    <questiontext>
     Do I love HTML/XML parsing?
    </questiontext>
    <questalter>
     <choice>
      1 oh god yeah
     </choice>
     <choice>
      2 that makes me feel good
     </choice>
     <choice>
      3 oh hmm noo
     </choice>
     <choice>
      4 totally
     </choice>
     </questalter>
     <answer>
      4
    </answer>
   </question>
  </questionaire>
 </body>
</html>
  

Комментарии:

1. Привет, Мэтт, спасибо за ваш ответ… это выглядит довольно сложно … интересно, есть ли решение с помощью BeautifulSoup или lxml …?

2. Я обновил свой ответ, чтобы он работал с вашим html. Имейте в виду, что у вас есть дополнительный <question> в конце, который вызовет ошибку синтаксического анализа.

3. Большое вам спасибо … я нашел этот минидом таким страшным, но это тоже выглядит красиво! Лично я предпочитаю lxml … хотел бы я принять два ответа 😉

Ответ №2:

 from lxml import etree
html = etree.fromstring(html_string)
questions = html.xpath('/html/body/questionaire/question')
for question in questions:
    for elements in question.getchildren():
        if element.tag == 'answer' and '99' in element.text:
            html.xpath('/html/body/questionaire')[0].remove(question)
print etree.tostring(html)