我的XML文件如下所示:
<strings>
<string>Bla <b>One & Two</b> Foo</string>
</strings>
我想提取每个&lt; string&gt;的内容同时保持内部标签。也就是说,我希望看到以下Python字符串:u“Bla&lt; b&gt; One&amp; Two&lt; / b&gt; Foo”。或者,我想我可以解决你的“Bla&lt; b&gt; One&amp; Two&lt; / b&gt; Foo”,然后尝试自己更换实体。
我目前正在使用lxml,它允许我迭代嵌套标签,错过标签内部的文本,或者错过所有文本内容(itertext),丢失标签信息。我可能错过了一些东西。
如果可能,我宁愿保留lxml,但如果有必要,我可以切换到另一个库。
答案 0 :(得分:3)
可能有一种更好的方法来有条件地处理xpath()
函数返回的对象,但我不熟悉lxml
知道它是什么,所以我不得不写一个函数来返回节点的文本值。但是,这说明了这个问题的一般方法:
>>> from lxml import etree
>>> from StringIO import StringIO
>>> def node_text(n):
try:
return etree.tostring(n, method='html', with_tail=False)
except TypeError:
return str(n)
>>> f = StringIO('<strings><string>This is <b>not</b> how I plan to escape.</string></strings>')
>>> x = etree.parse(f)
>>> ''.join(node_text(n) for n in x.xpath('/strings/string/node()'))
'This is <b>not</b> how I plan to escape.'
答案 1 :(得分:2)
outer = etree.tostring(string_elem, method='html')
inner = re.match("^[^>]+>(.*)<[^<]+$", outer).groups(1)[0]
答案 2 :(得分:0)
无论语言如何,相对简单的XSLT模板都可以解决问题。
类似于为要保留的标记定义模式,转换为其他文本。
您当然可以使用具有兼容DOM实现的递归函数(minidom可能?)并手动处理标记。
(伪代码)
def Function(tag):
if tag.NodeType = "#text": return tag.innerText
text=""
if tag.ElementName in allowedTags:
text="<%s>"%tag.ElementName
text += [Function(subtag) for subtag in tag.childs]
if tag.ElementName in allowedTags:
text+="</%s>"%tag.ElementName
return text
答案 3 :(得分:-1)
不使用解析器,只是纯粹的字符串操作
mystring="""
<strings>
<string>Bla <b>One & Two</b> Foo</string>
</strings>
"""
for s in mystring.split("</string>"):
if "<string>" in s:
i = s.index("<string>")
print s[i+len("<string>"):].replace("&","")