我正在尝试使用python和amp;删除2个标记之间的XML文档中的所有内容。 LXML。问题是标签可以在树的不同分支中(但总是在相同的深度),示例文档可能看起来像这样。
<root>
<p> Hello world <start />this is a paragraph </p>
<p> Goodbye world. <end />I'm leaving now </p>
</root>
我想删除开始和结束标记之间的所有内容。这将导致单个p标签:
<root>
<p> Hello world I'm leaving now </p>
</root>
有没有人知道如何使用lxml&amp; amp;蟒?
答案 0 :(得分:1)
你的手上乱七八糟,应该拍打那些故意歪曲XML嵌套规则的人。
您可能最好使用SAX之类的内容来识别<start/>
标记,并在点击<end/>
之前开始丢弃输入。 SAX在这里优于lxml,因为它允许你在每个lexeme中采取任意操作,而lxml在你触摸它们之前已经离开了开始和结束。
当您使用它时,您可能希望将这些文档转换为可用的XML。
答案 1 :(得分:1)
我知道有些人会想要为此辩护,但你可以使用正则表达式:
import re
new_string = re.sub(r'<start />(.*?)<end />', '', your_string, re.S)
如果XML解析器不是有效的XML,则无法使用它。
答案 2 :(得分:0)
您可以尝试使用类似SAX的target parser interface:
from lxml import etree
class SkipStartEndTarget:
def __init__(self, *args, **kwargs):
self.builder = etree.TreeBuilder()
self.skip = False
def start(self, tag, attrib, nsmap=None):
if tag == 'start':
self.skip = True
if not self.skip:
self.builder.start(tag, attrib, nsmap)
def data(self, data):
if not self.skip:
self.builder.data(data)
def comment(self, comment):
if not self.skip:
self.builder.comment(self)
def pi(self, target, data):
if not self.skip:
self.builder.pi(target, data)
def end(self, tag):
if not self.skip:
self.builder.end(tag)
if tag == 'end':
self.skip = False
def close(self):
self.skip = False
return self.builder.close()
然后,您可以使用SkipStartEndTarget
类制作parser target
,并使用该目标创建自定义XMLParser
,如下所示:
parser = etree.XMLParser(target=SkipStartEndTarget())
如果需要,您仍然可以为解析器提供其他解析器选项。然后,您可以将此解析器提供给您正在使用的解析器函数,例如:
elem = etree.fromstring(xml_str, parser=parser)
这也适用于etree.XML()
和etree.parse()
,您甚至可以将解析器设置为etree.setdefaultparser()
的默认解析器(这可能不是一个好主意)。有一件事可能会让你感到惊讶:即使使用etree.parse()
,这也不会返回元素树,但总是一个元素(如etree.XML()
和etree.fromstring()
所做)。我不认为这可以(但是),所以如果这对你来说是一个问题,你将不得不以某种方式解决它。
请注意,也可以使用带有lxml.sax的sax事件创建一个elementtree,这可能有点困难和慢。与上面的示例相反,它将返回一个elementtree,但我认为它不提供正常使用.docinfo
时会得到的etree.parse()
。我也相信它(目前)不支持评论和pi。 (还没用过,所以我现在不能再精确了)
另请注意,任何类似SAX的解析文档的方法都要求跳过<start/>
和<end/>
之间的所有内容仍然会生成格式正确的文档,在您的示例中就是这种情况,但是例如,如果第二个<p>
是<p2>
,则不会是这种情况,因为您最终会得到<p>....</p2>
。