我编写了一个继承自 xml.etree.ElementTree.Element 类的类,以使用显示 etree 元素的完整标签名称的方法扩展该类,以及一种用 XML 值替换元素完整内容的简单方法细绳..
在新类的init方法中,我只想在实例化时将 etree 元素的副本作为参数传递。
第一次尝试是:
def __init__(self, elem):
self = elem
但是随后传递的“元素”的“子标签”列表丢失了。
下面的解决方案有效,但是否有一种“更智能”的方法可以将完整的“elem”复制到新对象中?
import xml.etree.ElementTree as ET
#
# this class allows to replace the content including all subelement of an etree element
# by an XML string content
#
class xmltag(ET.Element):
# constructor
def __init__(self, elem):
self.tag = elem.tag
self.text = elem.text
self.attrib = elem.attrib
self.tail = elem.tail
for s in next(elem.iter()):
self.append(s)
# get string of complete start tag name
def __get_tag_start(self):
tag="<"+self.tag
for k in self.attrib.keys():
tag=tag+" "+k+"=\"" + self.attrib[k] + "\""
return tag+">"
# get string of end tag name
def __get_tag_end(self):
return "</" + self.tag + ">" + (self.tail or "")
# get string of whole content between start and end tag
def get_tag_content(self):
content=self.text or ""
for s in next(self.iter()):
xs=xmltag(s)
content=content+xs.__get_tag_start()
content=content+(xs.text or "")
content=content+xs.__get_tag_end()
return content
# change tag name
def set_tag_name(self,tagname):
self.tag=tagname
# change content
def set_tag_content(self,content):
try:
elem=ET.fromstring(self.__get_tag_start()+content+self.__get_tag_end())
self.clear()
self.tag = elem.tag
self.text = elem.text
self.attrib = elem.attrib
self.tail = elem.tail
for s in next(elem.iter()):
self.append(s)
elem.clear()
except:
pass
#
# testdata
#
xmldata="""<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>"""
#
# MAIN
#
if __name__ == "__main__":
root = ET.fromstring(xmldata)
element=root.find("country")
if ET.iselement(element):
x=xmltag(element)
print(x.get_tag_content())
x.set_tag_content("abc")
print(ET.tostring(x,encoding="unicode"))
x.set_tag_content("EFG")
print(ET.tostring(x,encoding="unicode"))
x.set_tag_name("test")
print(ET.tostring(x,encoding="unicode"))