2012-05-03 2 views
4

Я пытаюсь создать скрипт python, который будет принимать XML-документ и удалить из него все блоки комментариев.Python скрипт для удаления всех комментариев из файла XML

Я пытался что-то вдоль линий:

tree = ElementTree() 
tree.parse(file) 
commentElements = tree.findall('//comment()') 

for element in commentElements: 
    element.parentNode.remove(element) 

Делать это дает странные ошибки из питона: «исключение KeyError:„()“

Я знаю, что есть способы легко редактировать файл, используя другие методы (как СЭД), но я должен сделать это в питон скрипт.

+1

Не могли бы вы добавить немного пример XML-документа? – Glider

+1

'' // comment() ''похоже, не является допустимым форматом пути поиска и вызывает KeyError. Можете ли вы включить этот образец XML и расширить шаблон, который вы пытаетесь поймать? – jdi

+2

'comment()' - это тест узла XPath, который не поддерживается ElementTree. Попробуйте [lxml] (http://lxml.de/xpathxslt.html#xpath), который имеет полную поддержку XPath 1.0. – mzjn

ответ

9

comment() - это тест узла XPath, который не поддерживается ElementTree.

Вы можете использовать comment() с lxml. Эта библиотека очень похожа на ElementTree и имеет полную поддержку XPath 1.0.

Вот как вы можете удалить комментарии с LXML:

from lxml import etree 

XML = """<root> 
    <!-- COMMENT 1 --> 
    <x>TEXT 1</x> 
    <y>TEXT 2 <!-- COMMENT 2 --></y> 
</root>""" 

tree = etree.fromstring(XML) 

comments = tree.xpath('//comment()') 

for c in comments: 
    p = c.getparent() 
    p.remove(c) 

print etree.tostring(tree) 

Выход:

<root> 
    <x>TEXT 1</x> 
    <y>TEXT 2 </y> 
</root> 
3

Это решение, которое я реализован с использованием minidom:

def removeCommentNodes(self): 
     for tag in self.dom.getElementsByTagName("*"): 
      for n in tag.childNodes: 
       if n.nodeType is dom.Node.COMMENT_NODE: 
        n.parentNode.removeChild(n) 

На практике я первый получить все теги в xml, затем для каждого тега я ищу узлы комментариев, и если они найдены, я удаляю их. (Self.dom является ссылкой на разобранного XML)

7

Используйте strip_tags() из lxml.etree

from lxml import etree 
XML = """<root> 
    <!-- COMMENT 1 --> 
    <x>TEXT 1</x> 
    <y>TEXT 2 <!-- COMMENT 2 --></y> 
    </root>""" 

tree = etree.fromstring(XML) 
print etree.tostring(tree) 
etree.strip_tags(tree,etree.Comment) 
print etree.tostring(tree) 

Выход:

<root> 
<!-- COMMENT 1 --> 
<x>TEXT 1</x> 
<y>TEXT 2 <!-- COMMENT 2 --></y> 
</root> 
<root> 

<x>TEXT 1</x> 
<y>TEXT 2 </y> 
</root> 
3

То же самое, как

https://stackoverflow.com/a/3317008/1458574

from lxml import etree 
import sys 

XML = open(sys.argv[1]).read() 
parser = etree.XMLParser(remove_comments=True) 
tree= etree.fromstring(XML, parser = parser) 
print etree.tostring(tree) 
+0

'remove_comments = True' отлично работает, но он не используется в связанном ответе. Так почему вы говорите, что это «одно и то же»? – mzjn

Смежные вопросы