1.什么是XML

XML是可扩展标记语言(Extensible Markup Language)的缩写,其中的 标记(markup)是关键部分。您可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。

XML有以下几个特点。

  • XML的设计宗旨是传输数据,而非显示数据。

  • XML标签没有被预定义。您需要自行定义标签。

  • XML被设计为具有自我描述性。

  • XML是W3C的推荐标准。

其解析流程如下图:

      

2.常用解析XML的Python包

Python的标准库中,提供了6种可以用于处理XML的包。

  xml.dom

  xml.dom实现的是W3C制定的DOM API。DOM解析器在任何处理开始之前,必须把基于XML文件生成的树状数据放在内存,所以DOM解析器的内存使用量完全根据输入资料的大小。

xml.dom.minidom

  xml.dom.minidom是DOM API的极简化实现,比完整版的DOM要简单的多,而且这个包也小的多。

xml.dom.pulldom

  与其他模块不同,xml.dom.pulldom模块提供的是一个“pull解析器”,其背后的基本概念指的是从XML 流中pull事件,然后进行处理。虽然与SAX一样采用事件驱动模型(event-driven processing model),但是不同的是,使用pull解析器时,使用者需要明确地从XML流中pull事件,并对这些事件遍历处理,直到处理完成或者出现错误。

xml.sax

  xml.sax模块实现的是SAX API,这个模块牺牲了便捷性来换取速度和内存占用。SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准。它是事件驱动的,并不需要一次性读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。

 xml.parser.expat

  xml.parser.expat提供了对C语言编写的expat解析器的一个直接的、底层API接口。expat接口与SAX类似,也是基于事件回调机制,但是这个接口并不是标准化的,只适用于expat库。expat是一个面向流的解析器。您注册的解析器回调(或handler)功能,然后开始搜索它的文档。当解析器识别该文件的指定的位置,它会调用 该部分相应的处理程序(如果您已经注册的一个)。该文件被输送到解析器,会被分割成多个片断,并分段装到内存中。因此expat可以解析那些巨大的文件。

   xml.etree.ElementTree(以下简称ET)

  xml.etree.ElementTree模块提供了一个轻量级、Pythonic的API,同时还有一个高效的C语言实现,即xml.etree.cElementTree。与DOM相比,ET的速度更快,API使用更直接、方便。与SAX相比,ET.iterparse函数同样提供了按需解析的功能,不会一次性在内存中读入整个文档。ET的性能与SAX模块大致相仿,但是它的API更加高层次,用户使用起来更加便捷。Python标准库中,提供了ET的两种实现。一个是纯Python实现的xml.etree.ElementTree,另一个是速度更快的C语言实现xml.etree.cElementTree。请记住始终使用C语言实现,因为它的速度要快很多,而且内存消耗也要少很多。如果你所使用的Python版本中没有cElementTree所需的加速模块,你可以这样导入模块:

  1. try:
  2. import xml.etree.cElementTree as ET
  3. except ImportError:
  4. import xml.etree.ElementTree as ET

  如果某个API存在不同的实现,上面是常见的导入方式。当然,很可能你直接导入第一个模块时,并不会出现问题。请注意,自Python 3.3之后,就不用采用上面的导入方法,因为ElemenTree模块会自动优先使用C加速器,如果不存在C实现,则会使用Python实现。因此,使用Python 3.3+的朋友,只需要import xml.etree.ElementTree即可。

3.将XML文档解析为树(tree)

  XML是一种结构化、层级化的数据格式,最适合体现XML的数据结构就是树。ET提供了两个对象:ElementTree将整个XML文档转化为树,Element则代表着树上的单个节点。对整个XML文档的交互(读取,写入,查找需要的元素),一般是在ElementTree层面进行的。对单个XML元素及其子元素,则是在Element层面进行的。

      

  XML是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。XML文件格式如下:

  1. <data>
  2. <country name="Liechtenstein">
  3. <rank updated="yes">2</rank>
  4. <year>2023</year>
  5. <gdppc>141100</gdppc>
  6. <neighbor direction="E" name="Austria" />
  7. <neighbor direction="W" name="Switzerland" />
  8. </country>
  9. <country name="Singapore">
  10. <rank updated="yes">5</rank>
  11. <year>2026</year>
  12. <gdppc>59900</gdppc>
  13. <neighbor direction="N" name="Malaysia" />
  14. </country>
  15. <country name="Panama">
  16. <rank updated="yes">69</rank>
  17. <year>2026</year>
  18. <gdppc>13600</gdppc>
  19. <neighbor direction="W" name="Costa Rica" />
  20. <neighbor direction="E" name="Colombia" />
  21. </country>
  22. </data>

1、解析XML(两种方式)

  a.利用ElementTree.XML将字符串解析成xml对象

  1. from xml.etree import ElementTree as ET
  2.  
  3. # 打开文件,读取XML内容
  4. str_xml = open('xo.xml', 'r').read()
  5.  
  6. # 将字符串解析成xml特殊对象,root代指xml文件的根节点
  7. root = ET.XML(str_xml)

  b.利用ElementTree.parse将文件直接解析成xml对象

  1. from xml.etree import ElementTree as ET
  2.  
  3. # 直接解析xml文件
  4. tree = ET.parse("xo.xml")
  5.  
  6. # 获取xml文件的根节点
  7. root = tree.getroot()

2、操作XML

  XML格式类型是节点嵌套节点,对于每一个节点均有以下功能,以便对当前节点进行操作:

  1. class Element:
  2. """An XML element.
  3.  
  4. This class is the reference implementation of the Element interface.
  5.  
  6. An element's length is its number of subelements. That means if you
  7. want to check if an element is truly empty, you should check BOTH
  8. its length AND its text attribute.
  9.  
  10. The element tag, attribute names, and attribute values can be either
  11. bytes or strings.
  12.  
  13. *tag* is the element name. *attrib* is an optional dictionary containing
  14. element attributes. *extra* are additional element attributes given as
  15. keyword arguments.
  16.  
  17. Example form:
  18. <tag attrib>text<child/>...</tag>tail
  19.  
  20. """
  21.  
  22. 当前节点的标签名
  23. tag = None
  24. """The element's name."""
  25.  
  26. 当前节点的属性
  27.  
  28. attrib = None
  29. """Dictionary of the element's attributes."""
  30.  
  31. 当前节点的内容
  32. text = None
  33. """
  34. Text before first subelement. This is either a string or the value None.
  35. Note that if there is no text, this attribute may be either
  36. None or the empty string, depending on the parser.
  37.  
  38. """
  39.  
  40. tail = None
  41. """
  42. Text after this element's end tag, but before the next sibling element's
  43. start tag. This is either a string or the value None. Note that if there
  44. was no text, this attribute may be either None or an empty string,
  45. depending on the parser.
  46.  
  47. """
  48.  
  49. def __init__(self, tag, attrib={}, **extra):
  50. if not isinstance(attrib, dict):
  51. raise TypeError("attrib must be dict, not %s" % (
  52. attrib.__class__.__name__,))
  53. attrib = attrib.copy()
  54. attrib.update(extra)
  55. self.tag = tag
  56. self.attrib = attrib
  57. self._children = []
  58.  
  59. def __repr__(self):
  60. return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))
  61.  
  62. def makeelement(self, tag, attrib):
  63. 创建一个新节点
  64. """Create a new element with the same type.
  65.  
  66. *tag* is a string containing the element name.
  67. *attrib* is a dictionary containing the element attributes.
  68.  
  69. Do not call this method, use the SubElement factory function instead.
  70.  
  71. """
  72. return self.__class__(tag, attrib)
  73.  
  74. def copy(self):
  75. """Return copy of current element.
  76.  
  77. This creates a shallow copy. Subelements will be shared with the
  78. original tree.
  79.  
  80. """
  81. elem = self.makeelement(self.tag, self.attrib)
  82. elem.text = self.text
  83. elem.tail = self.tail
  84. elem[:] = self
  85. return elem
  86.  
  87. def __len__(self):
  88. return len(self._children)
  89.  
  90. def __bool__(self):
  91. warnings.warn(
  92. "The behavior of this method will change in future versions. "
  93. "Use specific 'len(elem)' or 'elem is not None' test instead.",
  94. FutureWarning, stacklevel=2
  95. )
  96. return len(self._children) != 0 # emulate old behaviour, for now
  97.  
  98. def __getitem__(self, index):
  99. return self._children[index]
  100.  
  101. def __setitem__(self, index, element):
  102. # if isinstance(index, slice):
  103. # for elt in element:
  104. # assert iselement(elt)
  105. # else:
  106. # assert iselement(element)
  107. self._children[index] = element
  108.  
  109. def __delitem__(self, index):
  110. del self._children[index]
  111.  
  112. def append(self, subelement):
  113. 为当前节点追加一个子节点
  114. """Add *subelement* to the end of this element.
  115.  
  116. The new element will appear in document order after the last existing
  117. subelement (or directly after the text, if it's the first subelement),
  118. but before the end tag for this element.
  119.  
  120. """
  121. self._assert_is_element(subelement)
  122. self._children.append(subelement)
  123.  
  124. def extend(self, elements):
  125. 为当前节点扩展 n 个子节点
  126. """Append subelements from a sequence.
  127.  
  128. *elements* is a sequence with zero or more elements.
  129.  
  130. """
  131. for element in elements:
  132. self._assert_is_element(element)
  133. self._children.extend(elements)
  134.  
  135. def insert(self, index, subelement):
  136. 在当前节点的子节点中插入某个节点,即:为当前节点创建子节点,然后插入指定位置
  137. """Insert *subelement* at position *index*."""
  138. self._assert_is_element(subelement)
  139. self._children.insert(index, subelement)
  140.  
  141. def _assert_is_element(self, e):
  142. # Need to refer to the actual Python implementation, not the
  143. # shadowing C implementation.
  144. if not isinstance(e, _Element_Py):
  145. raise TypeError('expected an Element, not %s' % type(e).__name__)
  146.  
  147. def remove(self, subelement):
  148. 在当前节点在子节点中删除某个节点
  149. """Remove matching subelement.
  150.  
  151. Unlike the find methods, this method compares elements based on
  152. identity, NOT ON tag value or contents. To remove subelements by
  153. other means, the easiest way is to use a list comprehension to
  154. select what elements to keep, and then use slice assignment to update
  155. the parent element.
  156.  
  157. ValueError is raised if a matching element could not be found.
  158.  
  159. """
  160. # assert iselement(element)
  161. self._children.remove(subelement)
  162.  
  163. def getchildren(self):
  164. 获取所有的子节点(废弃)
  165. """(Deprecated) Return all subelements.
  166.  
  167. Elements are returned in document order.
  168.  
  169. """
  170. warnings.warn(
  171. "This method will be removed in future versions. "
  172. "Use 'list(elem)' or iteration over elem instead.",
  173. DeprecationWarning, stacklevel=2
  174. )
  175. return self._children
  176.  
  177. def find(self, path, namespaces=None):
  178. 获取第一个寻找到的子节点
  179. """Find first matching element by tag name or path.
  180.  
  181. *path* is a string having either an element tag or an XPath,
  182. *namespaces* is an optional mapping from namespace prefix to full name.
  183.  
  184. Return the first matching element, or None if no element was found.
  185.  
  186. """
  187. return ElementPath.find(self, path, namespaces)
  188.  
  189. def findtext(self, path, default=None, namespaces=None):
  190. 获取第一个寻找到的子节点的内容
  191. """Find text for first matching element by tag name or path.
  192.  
  193. *path* is a string having either an element tag or an XPath,
  194. *default* is the value to return if the element was not found,
  195. *namespaces* is an optional mapping from namespace prefix to full name.
  196.  
  197. Return text content of first matching element, or default value if
  198. none was found. Note that if an element is found having no text
  199. content, the empty string is returned.
  200.  
  201. """
  202. return ElementPath.findtext(self, path, default, namespaces)
  203.  
  204. def findall(self, path, namespaces=None):
  205. 获取所有的子节点
  206. """Find all matching subelements by tag name or path.
  207.  
  208. *path* is a string having either an element tag or an XPath,
  209. *namespaces* is an optional mapping from namespace prefix to full name.
  210.  
  211. Returns list containing all matching elements in document order.
  212.  
  213. """
  214. return ElementPath.findall(self, path, namespaces)
  215.  
  216. def iterfind(self, path, namespaces=None):
  217. 获取所有指定的节点,并创建一个迭代器(可以被for循环)
  218. """Find all matching subelements by tag name or path.
  219.  
  220. *path* is a string having either an element tag or an XPath,
  221. *namespaces* is an optional mapping from namespace prefix to full name.
  222.  
  223. Return an iterable yielding all matching elements in document order.
  224.  
  225. """
  226. return ElementPath.iterfind(self, path, namespaces)
  227.  
  228. def clear(self):
  229. 清空节点
  230. """Reset element.
  231.  
  232. This function removes all subelements, clears all attributes, and sets
  233. the text and tail attributes to None.
  234.  
  235. """
  236. self.attrib.clear()
  237. self._children = []
  238. self.text = self.tail = None
  239.  
  240. def get(self, key, default=None):
  241. 获取当前节点的属性值
  242. """Get element attribute.
  243.  
  244. Equivalent to attrib.get, but some implementations may handle this a
  245. bit more efficiently. *key* is what attribute to look for, and
  246. *default* is what to return if the attribute was not found.
  247.  
  248. Returns a string containing the attribute value, or the default if
  249. attribute was not found.
  250.  
  251. """
  252. return self.attrib.get(key, default)
  253.  
  254. def set(self, key, value):
  255. 为当前节点设置属性值
  256. """Set element attribute.
  257.  
  258. Equivalent to attrib[key] = value, but some implementations may handle
  259. this a bit more efficiently. *key* is what attribute to set, and
  260. *value* is the attribute value to set it to.
  261.  
  262. """
  263. self.attrib[key] = value
  264.  
  265. def keys(self):
  266. 获取当前节点的所有属性的 key
  267.  
  268. """Get list of attribute names.
  269.  
  270. Names are returned in an arbitrary order, just like an ordinary
  271. Python dict. Equivalent to attrib.keys()
  272.  
  273. """
  274. return self.attrib.keys()
  275.  
  276. def items(self):
  277. 获取当前节点的所有属性值,每个属性都是一个键值对
  278. """Get element attributes as a sequence.
  279.  
  280. The attributes are returned in arbitrary order. Equivalent to
  281. attrib.items().
  282.  
  283. Return a list of (name, value) tuples.
  284.  
  285. """
  286. return self.attrib.items()
  287.  
  288. def iter(self, tag=None):
  289. 在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器(可以被for循环)。
  290. """Create tree iterator.
  291.  
  292. The iterator loops over the element and all subelements in document
  293. order, returning all elements with a matching tag.
  294.  
  295. If the tree structure is modified during iteration, new or removed
  296. elements may or may not be included. To get a stable set, use the
  297. list() function on the iterator, and loop over the resulting list.
  298.  
  299. *tag* is what tags to look for (default is to return all elements)
  300.  
  301. Return an iterator containing all the matching elements.
  302.  
  303. """
  304. if tag == "*":
  305. tag = None
  306. if tag is None or self.tag == tag:
  307. yield self
  308. for e in self._children:
  309. yield from e.iter(tag)
  310.  
  311. # compatibility
  312. def getiterator(self, tag=None):
  313. # Change for a DeprecationWarning in 1.4
  314. warnings.warn(
  315. "This method will be removed in future versions. "
  316. "Use 'elem.iter()' or 'list(elem.iter())' instead.",
  317. PendingDeprecationWarning, stacklevel=2
  318. )
  319. return list(self.iter(tag))
  320.  
  321. def itertext(self):
  322. 在当前节点的子孙中根据节点名称寻找所有指定的节点的内容,并返回一个迭代器(可以被for循环)。
  323. """Create text iterator.
  324.  
  325. The iterator loops over the element and all subelements in document
  326. order, returning all inner text.
  327.  
  328. """
  329. tag = self.tag
  330. if not isinstance(tag, str) and tag is not None:
  331. return
  332. if self.text:
  333. yield self.text
  334. for e in self:
  335. yield from e.itertext()
  336. if e.tail:
  337. yield e.tail

  由于 每个节点 都具有以上的方法,并且在上一步骤中解析时均得到了root(xml文件的根节点),所以可以利用以上方法进行操作xml文件。

  a. 遍历XML文档的所有内容

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析方式一 ############
  4. """
  5. # 打开文件,读取XML内容
  6. str_xml = open('xo.xml', 'r').read()
  7.  
  8. # 将字符串解析成xml特殊对象,root代指xml文件的根节点
  9. root = ET.XML(str_xml)
  10. """
  11. ############ 解析方式二 ############
  12.  
  13. # 直接解析xml文件
  14. tree = ET.parse("xo.xml")
  15.  
  16. # 获取xml文件的根节点
  17. root = tree.getroot()
  18.  
  19. ### 操作
  20.  
  21. # 顶层标签
  22. print(root.tag)
  23.  
  24. # 遍历XML文档的第二层
  25. for child in root:
  26. # 第二层节点的标签名称和标签属性
  27. print(child.tag, child.attrib)
  28. # 遍历XML文档的第三层
  29. for i in child:
  30. # 第二层节点的标签名称和内容
  31. print(i.tag,i.text)

  b.遍历XML中指定的节点

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析方式一 ############
  4. """
  5. # 打开文件,读取XML内容
  6. str_xml = open('xo.xml', 'r').read()
  7.  
  8. # 将字符串解析成xml特殊对象,root代指xml文件的根节点
  9. root = ET.XML(str_xml)
  10. """
  11. ############ 解析方式二 ############
  12.  
  13. # 直接解析xml文件
  14. tree = ET.parse("xo.xml")
  15.  
  16. # 获取xml文件的根节点
  17. root = tree.getroot()
  18.  
  19. ### 操作
  20.  
  21. # 顶层标签
  22. print(root.tag)
  23.  
  24. # 遍历XML中所有的year节点
  25. for node in root.iter('year'):
  26. # 节点的标签名称和内容
  27. print(node.tag, node.text)

  c.修改节点内容

  由于修改的节点时,均是在内存中进行,其不会影响文件中的内容。所以,如果想要修改,则需要重新将内存中的内容写到文件。

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析方式一 ############
  4.  
  5. # 打开文件,读取XML内容
  6. str_xml = open('xo.xml', 'r').read()
  7.  
  8. # 将字符串解析成xml特殊对象,root代指xml文件的根节点
  9. root = ET.XML(str_xml)
  10.  
  11. ############ 操作 ############
  12.  
  13. # 顶层标签
  14. print(root.tag)
  15.  
  16. # 循环所有的year节点
  17. for node in root.iter('year'):
  18. # 将year节点中的内容自增一
  19. new_year = int(node.text) + 1
  20. node.text = str(new_year)
  21.  
  22. # 设置属性
  23. node.set('name', 'alex')
  24. node.set(')
  25. # 删除属性
  26. del node.attrib['name']
  27.  
  28. ############ 保存文件 ############
  29. tree = ET.ElementTree(root)
  30. tree.write("newnew.xml", encoding='utf-8')

解析字符串方式,修改,保存

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析方式二 ############
  4.  
  5. # 直接解析xml文件
  6. tree = ET.parse("xo.xml")
  7.  
  8. # 获取xml文件的根节点
  9. root = tree.getroot()
  10.  
  11. ############ 操作 ############
  12.  
  13. # 顶层标签
  14. print(root.tag)
  15.  
  16. # 循环所有的year节点
  17. for node in root.iter('year'):
  18. # 将year节点中的内容自增一
  19. new_year = int(node.text) + 1
  20. node.text = str(new_year)
  21.  
  22. # 设置属性
  23. node.set('name', 'alex')
  24. node.set(')
  25. # 删除属性
  26. del node.attrib['name']
  27.  
  28. ############ 保存文件 ############
  29. tree.write("newnew.xml", encoding='utf-8')

解析文件方式打开,修改,保存

  d.删除节点

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析字符串方式打开 ############
  4.  
  5. # 打开文件,读取XML内容
  6. str_xml = open('xo.xml', 'r').read()
  7.  
  8. # 将字符串解析成xml特殊对象,root代指xml文件的根节点
  9. root = ET.XML(str_xml)
  10.  
  11. ############ 操作 ############
  12.  
  13. # 顶层标签
  14. print(root.tag)
  15.  
  16. # 遍历data下的所有country节点
  17. for country in root.findall('country'):
  18. # 获取每一个country节点下rank节点的内容
  19. rank = int(country.find('rank').text)
  20.  
  21. if rank > 50:
  22. # 删除指定country节点
  23. root.remove(country)
  24.  
  25. ############ 保存文件 ############
  26. tree = ET.ElementTree(root)
  27. tree.write("newnew.xml", encoding='utf-8')

解析字符串方式打开,删除,保存

  1. from xml.etree import ElementTree as ET
  2.  
  3. ############ 解析方式二 ############
  4.  
  5. # 直接解析xml文件
  6. tree = ET.parse("xo.xml")
  7.  
  8. # 获取xml文件的根节点
  9. root = tree.getroot()
  10.  
  11. ############ 操作 ############
  12.  
  13. # 顶层标签
  14. print(root.tag)
  15.  
  16. # 循环所有的year节点
  17. for node in root.iter('year'):
  18. # 将year节点中的内容自增一
  19. new_year = int(node.text) + 1
  20. node.text = str(new_year)
  21.  
  22. # 设置属性
  23. node.set('name', 'alex')
  24. node.set(')
  25. # 删除属性
  26. del node.attrib['name']
  27.  
  28. ############ 保存文件 ############
  29. tree.write("newnew.xml", encoding='utf-8')
  30.  
  31. 解析文件方式,修改,保存

解析文件方式打开,删除,保存

3、创建XML文档

  1. from xml.etree import ElementTree as ET
  2.  
  3. # 创建根节点
  4. root = ET.Element("famliy")
  5.  
  6. # 创建节点大儿子
  7. son1 = ET.Element('son', {'name': '儿1'})
  8. # 创建小儿子
  9. son2 = ET.Element('son', {"name": '儿2'})
  10.  
  11. # 在大儿子中创建两个孙子
  12. grandson1 = ET.Element('grandson', {'name': '儿11'})
  13. grandson2 = ET.Element('grandson', {'name': '儿12'})
  14. son1.append(grandson1)
  15. son1.append(grandson2)
  16.  
  17. # 把儿子添加到根节点中
  18. root.append(son1)
  19. root.append(son1)
  20.  
  21. tree = ET.ElementTree(root)
  22. tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

创建方式一

  1. from xml.etree import ElementTree as ET
  2.  
  3. # 创建根节点
  4. root = ET.Element("famliy")
  5.  
  6. # 创建大儿子
  7. # son1 = ET.Element('son', {'name': '儿1'})
  8. son1 = root.makeelement('son', {'name': '儿1'})
  9. # 创建小儿子
  10. # son2 = ET.Element('son', {"name": '儿2'})
  11. son2 = root.makeelement('son', {"name": '儿2'})
  12.  
  13. # 在大儿子中创建两个孙子
  14. # grandson1 = ET.Element('grandson', {'name': '儿11'})
  15. grandson1 = son1.makeelement('grandson', {'name': '儿11'})
  16. # grandson2 = ET.Element('grandson', {'name': '儿12'})
  17. grandson2 = son1.makeelement('grandson', {'name': '儿12'})
  18.  
  19. son1.append(grandson1)
  20. son1.append(grandson2)
  21.  
  22. # 把儿子添加到根节点中
  23. root.append(son1)
  24. root.append(son1)
  25.  
  26. tree = ET.ElementTree(root)
  27. tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

创建方式二

  1. from xml.etree import ElementTree as ET
  2.  
  3. # 创建根节点
  4. root = ET.Element("famliy")
  5.  
  6. # 创建节点大儿子
  7. son1 = ET.SubElement(root, "son", attrib={'name': '儿1'})
  8. # 创建小儿子
  9. son2 = ET.SubElement(root, "son", attrib={"name": "儿2"})
  10.  
  11. # 在大儿子中创建一个孙子
  12. grandson1 = ET.SubElement(son1, "age", attrib={'name': '儿11'})
  13. grandson1.text = '孙子'
  14.  
  15. et = ET.ElementTree(root) #生成文档对象
  16. et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)

创建方式三

  由于原生保存的XML时默认无缩进,如果想要设置缩进的话, 需要修改保存方式:

  1. from xml.etree import ElementTree as ET
  2. from xml.dom import minidom
  3.  
  4. def prettify(elem):
  5. """将节点转换成字符串,并添加缩进。
  6. """
  7. rough_string = ET.tostring(elem, 'utf-8')
  8. reparsed = minidom.parseString(rough_string)
  9. return reparsed.toprettyxml(indent="\t")
  10.  
  11. # 创建根节点
  12. root = ET.Element("famliy")
  13.  
  14. # 创建大儿子
  15. # son1 = ET.Element('son', {'name': '儿1'})
  16. son1 = root.makeelement('son', {'name': '儿1'})
  17. # 创建小儿子
  18. # son2 = ET.Element('son', {"name": '儿2'})
  19. son2 = root.makeelement('son', {"name": '儿2'})
  20.  
  21. # 在大儿子中创建两个孙子
  22. # grandson1 = ET.Element('grandson', {'name': '儿11'})
  23. grandson1 = son1.makeelement('grandson', {'name': '儿11'})
  24. # grandson2 = ET.Element('grandson', {'name': '儿12'})
  25. grandson2 = son1.makeelement('grandson', {'name': '儿12'})
  26.  
  27. son1.append(grandson1)
  28. son1.append(grandson2)
  29.  
  30. # 把儿子添加到根节点中
  31. root.append(son1)
  32. root.append(son1)
  33.  
  34. raw_str = prettify(root)
  35.  
  36. f = open("xxxoo.xml",'w',encoding='utf-8')
  37. f.write(raw_str)
  38. f.close()

4、命名空间

  XML 命名空间提供避免元素命名冲突的方法。在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。

  1. <table>
  2. <tr>
  3. <td>Apples</td>
  4. <td>Bananas</td>
  5. </tr>
  6. </table>
  7.  
  8. <table>
  9. <name>African Coffee Table</name>
  10. <width>80</width>
  11. <length>120</length>
  12. </table>
  13.  
  14. 假如这两个 XML 文档被一起使用,由于两个文档都包含带有不同内容和定义的 <table> 元素,就会发生命名冲突。
  15. XML 解析器无法确定如何处理这类冲突。

  要解决上述办法:采用命名空间

  1. <h:table xmlns:h="http://www.w3.org/TR/html4/">
  2. <h:tr>
  3. <h:td>Apples</h:td>
  4. <h:td>Bananas</h:td>
  5. </h:tr>
  6. </h:table>
  7.  
  8. <f:table xmlns:f="http://www.w3school.com.cn/furniture">
  9. <f:name>African Coffee Table</f:name>
  10. <f:width>80</f:width>
  11. <f:length>120</f:length>
  12. </f:table>

  在python中的解决办法:

  1. from xml.etree import ElementTree as ET
  2.  
  3. ET.register_namespace('com',"http://www.company.com") #some name
  4.  
  5. # build a tree structure
  6. root = ET.Element("{http://www.company.com}STUFF")
  7. body = ET.SubElement(root, "})
  8. body.text = "STUFF EVERYWHERE!"
  9.  
  10. # wrap it in an ElementTree instance, and save as XML
  11. tree = ET.ElementTree(root)
  12.  
  13. tree.write("page.xml",
  14. xml_declaration=True,
  15. encoding='utf-8',
  16. method="xml")

5.说明事项

  • 不要使用xml.py作为文件名,否则此时会发生如下错误:ImportError: No module named 'xml.etree'; 'xml' is not a package.注意:删除xml.py后仍然不能成功解释,那是因为当前路径中还生成了xml.pyc,而该文件的优先级要高于xml.py,因此解释器还是优先在xml.pyc中寻找,因此必须将该文件也删除掉,成功解决问题。
  • ElementTree模块中提供的很多解析函数都需要预先将整个XML文档读入内存中,这对于大型XML解析而言,不是一件好事,尤其是当我们从网络、管道中读取XML时,非阻塞式的解析非常重要。此时,我们可以使用ElementTree模块中的XMLPullParse类来处理。当然我们也可以选择ElementTree模块的iterparse()来代替,该方法在解析大型XML时也不需要全部读入内存。参考以下代码
  1. count = 0
  2. for event, elem in ET.iterparse(sys.argv[2]):
  3. if event == 'end':
  4. if elem.tag == 'location' and elem.text == 'Zimbabwe':
  5. count += 1
  6. elem.clear() # 将元素废弃
  7.  
  8. print count

[python标准库]XML模块的更多相关文章

  1. python标准库xml.etree.ElementTree的bug

    使用python生成或者解析xml的方法用的最多的可能就数python标准库xml.etree.ElementTree和lxml了,在某些环境下使用xml.etree.ElementTree更方便一些 ...

  2. [python标准库]Pickle模块

    Pickle-------python对象序列化 本文主要阐述以下几点: 1.pickle模块简介 2.pickle模块提供的方法 3.注意事项 4.实例解析 1.pickle模块简介 The pic ...

  3. Python 标准库 ConfigParser 模块 的使用

    Python 标准库 ConfigParser 模块 的使用 demo #!/usr/bin/env python # coding=utf-8 import ConfigParser import ...

  4. Python标准库——collections模块的Counter类

    1.collections模块 collections模块自Python 2.4版本开始被引入,包含了dict.set.list.tuple以外的一些特殊的容器类型,分别是: OrderedDict类 ...

  5. 【python】Python标准库defaultdict模块

    来源:http://www.ynpxrz.com/n1031711c2023.aspx Python标准库中collections对集合类型的数据结构进行了很多拓展操作,这些操作在我们使用集合的时候会 ...

  6. Python标准库--os模块

    这个模块包含普遍的操作系统功能.如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的.即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在Linux和Windows下运行.一个例 ...

  7. python标准库 bisect模块

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #bisect #作用:维护有序列表,而不必在每次向列表增加一个元素 ...

  8. python标准库 sysconfig模块

    # -*- coding: utf-8 -*-# python:2.x__author__ = 'Administrator'import sysconfig#sysconfig:解释器编译时配置#作 ...

  9. Python标准库 -- UUID模块(生成唯一标识)

    UUID是什么: UUID: 通用唯一标识符 ( Universally Unique Identifier ),对于所有的UUID它可以保证在空间和时间上的唯一性,也称为GUID,全称为: UUID ...

随机推荐

  1. Android 性能优化——之控件的优化

    Android 性能优化——之控件的优化 前面讲了图像的优化,接下来分享一下控件的性能优化,这里主要是面向自定义View的优化. 1.首先先说一下我们在自定义View中可能会犯的3个错误: 1)Use ...

  2. time模块简介

    Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能. Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间. 时间间隔是以秒为单位的浮点小数. ...

  3. phpcms基础

    CSM基础(做中小型企业网站) 做一个企业站,三个页面比较重要1.首页2.列表页3.内容页 做企业站的流程:1.由美工出一张,设计效果图2.将设计图静态化3.开始安装CMS4.强模板文件放到CSM里面 ...

  4. Linux基础(7)

    Linux 基础(7) 一.内存的监控(free) free -m 以单位为MB的方式查看内存的使用情况(free命令读取的文件是/proc/meminfo) total:是指计算机安装的内存总量 u ...

  5. xmlplus 组件设计系列之六 - 下拉刷新

    "下拉刷新"由著名设计师 Loren Brichter 设计,并应用于 Twitter 第三方应用 Tweetie 中.2010年4月,Twitter 收购 Tweetie 开发商 ...

  6. 【正常向】CODEVS上分黄金

    白银上分黄金失败=.= 在之前有很认真的写了一波排序,所以排序并不是很怂,还是那个理,现阶段学习的都是比较简单的排序,都是所谓的冒泡排序啊,桶排序这类,至于插排和选择排序,再往后又是什么快拍就很尬了. ...

  7. DFB系列 之 Clear清空surface缓存

    1. 函数原型解析 函数声明: DFBResult Clear (     IDirectFBSurface    *  thiz,      u8     r,      u8     g,     ...

  8. express4.x的使用

    ①.安装 npm install -g  express   ②.创建应用 express [目录] 会在目录下生成 node_modules, 存放所有的项目依赖库.(每个项目管理自己的依赖,与Ma ...

  9. hdu1698线段树区间更新

    题目链接:https://vjudge.net/contest/66989#problem/E 坑爹的线段树照着上一个线段树更新写的,结果发现有一个地方就是不对,找了半天,发现是延迟更新标记加错了!! ...

  10. [luoguP2912] [USACO08OCT]牧场散步Pasture Walking(lca)

    传送门 水题. 直接倍增求lca. x到y的距离为dis[x] + dis[y] - 2 * dis[lca(x, y)] ——代码 #include <cstdio> #include ...