lxml处理CDATA的备忘
lxml是python的库,可用于解析、处理xml文件及HTML文件。
在工作中,遇到需要对原有的xml文件进行改写,根据需要增加、删除或改写一些元素。具体的做法是先用lxml将文件解析为内存里的dom树结构,再通过lxml提供的方法对元素进行增、删、改、查等操作,最后再将内存里的dom树落回文件。
示例代码如下:
1 from lxml import etree 2 root = etree.fromstring(str_xml) # here parse dom tree from a xml string. 3 4 # here do some update on root. 5 # ........ 6 # update finish. 7 8 str_final_xml = etree.tostring(self.root, encoding='utf-8', xml_declaration=True) # here serialize dom tree to a string.
先解析,然后通过一系列查找,修改,增加,删除等操作,root对应的dom树变为我们想要的结果,再将结果dom树序列化为字符串。
这里遇到了一个问题。
原来的CDATA标签在重新写入后都不见了。在网上找了一些讨论,才知道原来CDATA在XML中不是必须的,所以默认去掉了。
如果想保留原来的CDATA,需要在解析xml时自己定义一个解析器。
代码如下所示:
1 from lxml import etree 2 3 parser = etree.XMLParser(strip_cdata=False) 4 root = etree.fromstring(str_xml, parser) # here parse dom tree from a xml string. 5 6 # here do some update on root. 7 # ........ 8 # update finish. 9 10 str_final_xml = etree.tostring(self.root, encoding='utf-8', xml_declaration=True) # here serialize dom tree to a string.
第3行自己定义了一个解析器,参数strip_cdata置为False,这个参数默认是开启的。在调用fromstring时带上这个解析器。这样将dom树再序列化后原始的CDATA就可以保留下来。
如果需要写入一个CDATA元素,lxml也能很高支持。
>>>elem = etree.Element('root') >>>elem.text = etree.CDATA('this is root.') >>> >>>print etree.tostring(elem)
<root><![CDATA[this is root.]]></root>
只需要将待写入的字符用etree.CDATA封装即可。