我需要解析并重建解析器使用的文件格式,该解析器使用的语言只能被称为XML。我意识到符合标准的XML并不关心CDATA或空白,但遗憾的是这个应用程序要求我关心这两个......
我使用lxml.etree
,因为它非常擅长保留CDATA。
例如:
s = '''
<root>
<item>
<![CDATA[whatever]]>
</item>
</root>'''
import lxml.etree as et
et.fromstring(s, et.XMLParser(strip_cdata=False))
item = root.find('item')
print et.tostring(item)
打印:
<item>
<![CDATA[whatever]]>
</item>
lxml
完全保留了<item>
代码的格式...很棒!
问题在于我无法确切地告诉CDATA在标签文本的开始和结束位置。属性item.text
没有说明CDATA包含文本的确切部分:
item.text
==> '\n whatever\n '
因此,如果我修改它,并尝试将其作为CDATA吐出,那么我将丢失空白的位置:
item.text = CDATA('foobar')
et.tostring(item)
==> '<item><![CDATA[foobar]]></item>\n'
显然,lxml
&#34;知道&#34; CDATA位于节点文本中的位置,因为它使用node.tostring()
保留它。但是,我无法找到一种方法来反省文本的哪些部分是CDATA,哪些不是。 有什么建议吗?
答案 0 :(得分:3)
我不确定lxml
,但使用minidom
,您可以更改CDATA部分并保留周围的空格,因为CDATASection
是一个单独的节点类型。< / p>
>>> from xml.dom import minidom
>>> data = minidom.parseString(s)
>>> parts = data.getElementsByTagName('item')
>>> item = parts[0]
>>> item.childNodes
[<DOM Text node "u'\n '">, <DOM CDATASection node "u'whatever'">, <DOM Text node "u'\n '">]
>>> item.childNodes[1].nodeValue = 'changed'
>>> print item.toxml()
<item>
<![CDATA[changed]]>
</item>
有关详细信息,请参阅xml.dom.minidom: Getting CDATA values。