《零基础学Python》Python和XML【十四】

整体文章目录

整体目录

一、 当前章节目录

在这里插入图片描述

二、XML介绍

2.1 XML的演进历史

  • 由于HTML扩展性不强,引入SGML发展成XML
  • XML定义:可扩展标记语言(XML)是标准通用标记语言(SGML)的一个子集。
  • 定义XML目的:使得在Web上能以现有超文本标记语言(HTML)的使用方式,接收和处理通用的SGML的方式成为可能。
  • XML设计需要考虑:现实的方便性,也要注意到不同语音之间的互操作性。

2.2 XML的优点和限制

优点:

  • 可以作为一个很好的数据交换方法,使得其成为很多配置文件的首选
  • 具有简单性。
  • 是自描述的,可供计算机处理,同时数据也可以重用。
  • 是一种结构化的语义标记语言,而不是一种数据表示语言。
  • 对于允许的元素方面非常灵活。

限制:

  • 但是本身并不具备数据处理的能力。
  • 保持着非常严格的语法检查。

2.3 XML技术的Python支持

  • SAX:

    • 事件驱动方式来处理XML文档:遇到特定标签调用指定方法,实现对特殊标签的处理。
    • 流数据方式来处理XML文档:读取部分数据后就进行处理,满足条件后终止对于XML文档解析。提高了处理速度。
  • DOM:

    • 通过树结构和数据来表示的信息集合。使得容易访问各个元素,添加、修改和删除特定的元素也是比较容易的。会消耗大量的内存和处理器时间。

三、XML文档概览和验证

3.1 XML文档的基础概念

<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<goods>
    <shirt>
        <name>Helen</name>
        <size>170</size>
        <quantity>10</quantity>
        <color>black</color>
    </shirt>
    <shirt>
        <name>First</name>
        <size>175</size>
        <quantity>9</quantity>
        <color>white</color>
    </shirt>
</goods>

3.2 XML文档的结构良好性验证

为使得XML文档成为一个结构良好的文档,需要遵守以下规则:

  1. 所有的开始标签必须有对应的结束标签。
  2. 元素可以嵌套,但是不能交叠。
  3. 有且只能有一个根元素。
  4. 属性值必须使用引号包含起来。
  5. 一个元素不能包含两个同名属性。
  6. 注释不能出现在标签内部。
  7. 没有转义的“<”或者“&”不能出现在元素和属性的字符中。
import xml.etree.ElementTree as ET
try:
    ET.parse(r"C:\Users\86155\8first.xml")
    print("这是一个良构的XML文档")
except Exceptionas as e:
    print("这可能是一个非良构文档")
    print("出错信息:", e)
<!--8first.xml-->
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<goods>
    <shirt>
        <name>Helen</name>
        <size>170</size>
        <quantity>10</quantity>
        <color>black</color>
    </shirt>
    <shirt>
        <name>First</name>
        <size>175</size>
        <quantity>9</quantity>
        <color>white</color>
    </shirt>
</goods>

运行结果:

这是一个良构的XML文档


<!--将</goods>改为<goods>-->
<goods>
	<!--省略部分代码-->
<goods>

运行结果:

这是一个非良构的XML文档


	<!--省略部分代码-->
	</goods>
</shirt>

运行结果:

这是一个非良构的XML文档


<!--省略部分代码-->
	</goods>
</shirt>

运行结果:

这是一个非良构的XML文档


<!--省略部分代码-->
</goods>
<goods></goods>

运行结果:

这是一个非良构的XML文档


<?xml version=1.0 encoding='utf-8' standalone='no' ?>
<!--省略部分代码-->

运行结果:

这是一个非良构的XML文档


# lxml可以通过异常的类别区分是不是非良构文档
import lxml.etree as ET		# 需要安装第三方库lxml
try:
    ET.parse(r"C:\Users\86155\8first.xml")
    print("这是一个良构的XML文档")
except SyntaxError as e:
    print("这可能是一个非良构文档")
    print("出错信息:", e)

3.3 XML文档的有效性验证

  • 为了规范XML文档中的元素及其使用方式,XML规范中通过使用DTD文件与XML Schema文件来对其进行描述。
  • XML Schema与DTD区别
    1. Schema本身也是XML文档,DTD定义跟XML没有什么关系,Schema在理解和实际应用有很多的好处。
    2. DTD文档的结构是“平铺型”的,如果定义复杂的XML文档,很难把握各元素之间的嵌套关系;Schema文档结构性强,各元素之间的嵌套关系非常直观
    3. DTD只能指定元素含有文本,不能定义元素文本的具体类型,如字符型、整型、日期型、自定义类型等。Schema在这方面比DTD强大。
    4. Schema支持元素节点顺序的描述,DTD没有提供无序情况的描述,要定义无序必需穷举排列的所有情况。Schema可以利用xs:all来表示无序的情况,继承了XML的自描述性和可扩展性。
    5. 对命名空间的支持。DTD无法利用XML的命名空间,Schema很好满足命名空间。并且,Schema还提供了include和import两种引用命名空间的方法。
    6. XML Schema不能像DTD一样定义实体,比DTD更复杂,但Xml Schema现在已是w3c组织的标准,它正逐步取代DTD。
  1. XML DTD本身的合法性却缺少较好的验证机制,必需独立处理。XML Schema则不同,它与XML有着同样的合法性验证机制
# DTD验证文档有效性
import lxml.etree as ET
dtd = ET.DTD('dtd_file.dtd')
f = open('xml_file.xml')
xml = ET.XML(f.read())
dtd.validate(xml)

In [1]: import lxml.etree as ET

In [2]: from io import StringIO

In [3]: f = StringIO("<!ELEMENT empty EMPTY>")

In [4]: dtd = ET.DTD(f)

In [5]: xml = ET.XML("<empty/>")

In [6]: dtd.validate(xml)
Out[6]: True

In [7]: xml = ET.XML("<empty>content</empty>")

In [8]: dtd.validate(xml)
Out[8]: False

In [9]: dtd.error_log.filter_from_errors()[0]
<string>:1:0:ERROR:VALID:DTD_NOT_EMPTY: Element empty was declared EMPTY this one has content

# XML Schema文档有效性验证
In [1]: import lxml.etree as ET

In [2]: from io import StringIO

In [3]: f = StringIO('''
		<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
		<xsd:element name="a" type="AType"/>
    		<xsd:complexType name="AType">
        		<xsd:sequence>
            		<xsd:element name="b" type="xsd:string"/>
        		</xsd:sequence>
    		</xsd:complexType>
		</xsd:schema>
		''')

In [4]: xmlschema_doc = ET.parse(f)

In [5]: xmlschema = ET.XMLSchema(xmlschema_doc)

In [6]: valid_str = StringIO('<a><b></b></a>')

In [7]: xml1 = ET.parse(valid_str)

In [8]: xmlschema.validate(xml1)
Out[8]: True

In [9]: invalid_str = StringIO('<a><c></c></a>')

In [10]: xml2 = ET.parse(invalid_str)

In [11]:xmlschema.validate(xml2)
Out[11]: False

In [12]: print(xmlschema.error_log)
<string>:1:0:ERROR:SCHEMASV:SCHEMAV_ELEMENT_CONTENT: Element 'c': This element is not expected. Expected is ( b ).

四、分析XML文档结构

4.1 XML的元素和标签

In [1]: import xml.etree.ElementTree as ET

In [2]: root = ET.Element("color")	# color为标签名

In [3]: root.text = "black"	# black为内容

In [4]: tree = ET.ElementTree(root)	# 

In [5]: tree.write('D:/xml1.xml', encoding = 'UTF-8')

In [6]: ET.ElementTree(ET.Element("br")).write('D:/xml2.xml', encoding='UTF-8')

In [7]: color = ET.Element("color")

In [8]: COLOR = ET.Element("COLOR")

In [9]: color.tag == COLOR.tag
Out[9]: False

In [10]: color_clone = ET.Element("color")

In [11]: color.tag == color_clone.tag
Out[11]: True

在这里插入图片描述

  • goods是根元素。
  • shirt是goods的子元素。
  • shirt是name、size、quantity、color的父元素。
  • name、size、quantity、color之间互为兄弟元素。
# 演示如何构建子元素
In [12]: root = ET.Element("goods")

In [13]: shirt = ET.SubElement(root,"shirt")

In [14]: name = ET.SubElement(shirt,"name")

In [15]: size = ET.SubElement(shirt,"size")

In [16]: tree = ET.ElementTree(root)

In [17]: tree.write('D:/xml3.xml', encoding='UTF-8')

In [18]: name.text = "Helen"

In [19]: size.text ="170"

In [20]: ET.dump(tree)
<goods><shirt><name>Helen</name><size>170</size></shirt></goods>

4.2 元素的属性

<!--xml3.xml-->
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<goods>
    <shirt quality="A">
        <name>Helen</name>
        <size>170</size>
        <quantity>10</quantity>
        <color>black</color>
    </shirt>
    <shirt quality='B'>
        <name>First</name>
        <size>175</size>
        <quantity>9</quantity>
        <color>white</color>
    </shirt>
</goods>

In [21]: shirt = ET.Element("shirt")

In [22]: shirt.attrib["quality"] = "A"

In [23]: ET.dump(shirt)
<shirt quality="A" />

In [24]: shirt = ET.Element("shirt", quality="A")

In [25]: ET.dump(shirt)
<shirt quality="A" />
<!--运行之后获得-->
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<goods>
    <shirt quality="A" size="170">
        <name>Helen</name>
        <size>170</size>
        <quantity>10</quantity>
        <color>black</color>
    </shirt>
    <shirt quality='B' size='175'>
        <name>First</name>
        <size>175</size>
        <quantity>9</quantity>
        <color>white</color>
    </shirt>
</goods>

4.3 XML的名字

对于使用Unicode字符的元素,可以在原来的文件中加入一个元素,其组成如下。

<牛仔裤 质量 = '一等品'>
	<品牌>西部传奇</品牌>
	<大小>175</大小>
	<数量>20</数量>
	<颜色>棕蓝色</颜色>
</牛仔裤>

在这里插入图片描述
在这里插入图片描述

# 非法字符解析将提示错误
In [27]: invalid = ET.Element("%my name")

In [28]: invalid.text = "content"

In [29]: ET.dump(invalid)
<%my name>content</%my name>

In [30]: from io import StringIO

In [31]: ET.parse(StringIO(ET.dump(invalid)))
<%my name>content</%my name>
Traceback (most recent call last):
# 省略部分输出
ParseError: no element found: line 1, column 0

4.4 字符实体

在这里插入图片描述

In [32]: entity_ref = ET.XML("<a>&lt;</a>")

In [33]: ET.dump(entity_ref)
<a>&lt;</a>

In [34]: entity_ref.text
'<'

In [35]: entity_ref = ET.XML("<a>&entity;</a>")
Traceback (most recent call last):
# 省略部分代码
ParseError: undefined entity: line 1, column

4.5 CDATA段

CDATA段用来声明不应被解析为标签的文本。(其中可以使用特殊字符,包括小于号、大于号和双引号等,而不必使用其字符实体。)

<?xml version="1.0" encoding="utf-8" standalone='no' ?>
<source>
    <function>
        <min>
            def min(x, y):
                if x < y: return x
                else: return y
        </min>
    </function>
</source>

在这里插入图片描述

<?xml version="1.0" encoding="utf-8" standalone='no' ?>
<source>
    <function>
        <min>
            def min(x, y):
                if x &lt; y: return x
                else: return y
        </min>
    </function>
</source>

在这里插入图片描述

<?xml version="1.0" encoding="utf-8" standalone='no' ?>
<source>
    <function>
        <min>
		<![CDATA[
            def min(x, y):
                if x &lt; y: return x
                else: return y
			]]>
        </min>
    </function>
</source>

在这里插入图片描述

4.6 注释

<!--这些货物信息还需要进一步核实-->
In [36]: xml_str="""<test>
		<!-- Comment -->
		content
		</test>
		"""
		
In [37]: tree = ET.XML(xml_str)

In [38]: ET.dump(tree)
<test>

content
</test>

4.7 处理指令

  • XML文档可以通过处理指令允许其包括用于特定应用的指令。
  • 一个处理指令通过"<?"和"?>"来界定。
  • 紧接在"<?"后面的是处理指令名,接着是属性值对。
  • 例如:<?robots index="yes" follow="no"?>

4.8 XML定义

<?xml version="1.0" encoding="ASCII" standalone="yes"?>
<name>
	Alice
</name>
  • encoding
    • 在XML定义中是可选的,如果省略的话,则默认采用了Unicode字符集。
    • 如果元信息和编码定义冲突的话,则会优先采用元信息。
  • standalone
    • 属性用来定义外部定义的DTD的存在性,取值可为yes或no,默认情况下为no。
    • 当为no的时候表示此XML文档不是独立的,而是取决于外部定义的DTD;
    • 而为yes则表示此XML文档是自包含的。这也是个可选的属性。

五、使用SAX处理XML文档

5.1 SAX介绍

SAX是一种流行的解析和处理XML文档的接口。
在这里插入图片描述
在这里插入图片描述

5.2 SAX处理的组成部分

  1. ContentHandler接口
from xml.sax import *
from io import StringIO

class MyHandler(ContentHandler):
    def startDocument(self):            # 开始处理文档的时候调用
        print("开始处理XML文档")
        print("================")
        print("name\tquality")
        print("================")

    def endDocument(self):              # 结束处理文档的时候调用
        print("================")
        print("结束处理XML文档")

    def startElement(self, name, attrs):    # 处理元素
        if name == "shirt":
            print("%s\t%s"%(attrs['name'], attrs['quality']))

parser = make_parser()      # 生成解析对象
parser.setContentHandler(MyHandler())

# 需要分析的XML数据
data = """<goods>
            <shirt name="Helen" quality="A" />
            <shirt name="Fayer" quality="A+" />
            <shirt name="Dayie" quality="B+" />
            <shirt name="CaC" quality="A-" />
            </goods>
"""
parser.parse(StringIO(data))

运行结果:

开始处理XML文档

================

name quality

================

Helen A
Fayer A+
Dayie B+
CaC A-

================
结束处理XML文档

  1. DTDHandler接口
class MyHandler(DTDHandler):
    pass
parser = make_parser()
parser.setDTDHandler(MyHandler())
  1. EntityResolver接口
class MyHandler(EntityResolver):
    pass
parser = make_parser()
parser.setEntityResolver(MyHandler())
  1. ErrorHandler接口
class MyHandler(EntityResolver):
    pass
parser = make_parser()
parser.setErrorHandler(MyHandler())
  1. XMLReader接口
class MyHandler(EntityResolver):
    pass
parser = make_parser()
handler = parser.getErrorHandler()

在这里插入图片描述
在这里插入图片描述

六、使用DOM处理XML文档

6.1 DOM介绍

DOM是另外一种流行的解析和处理XML文档的接口规范,可以用来访问XML文档中的数据。
在这里插入图片描述

6.2 xml.dom模块中的接口操作

  1. DOMImplemetation接口
In [1]: from xml.dom.minidom import DOMImplementation

In [2]: implementation = DOMImplementation()

In [3]: implementation.hasFeature("Core", "2.0")
Out[3]: True

In [4]: implementation.hasFeature("Events", "2.0")
Out[4]: False

In [5]: implementation._features
Out[5]: [('core', '1.0'),
		 ('core', '2.0'),
		 ('core', None),
		 ('xml', '1.0'),
		 ('xml', '2.0'),
		 ('xml', None),
		 ('ls-load', '3.0'),
		 ('ls-load', None)]
		 
In [6]: doctype = implementation.createDocumentType("Goods", "", "Goods.dtd")

In [7]: document = implementation.createDocument("", "goods", doctype)

In [8]: document
Out[8]: <xml.dom.minidom.Document at 0x18aaf8e0f40>
  1. Document接口
In [1]: from xml.dom.minidom import parse,parseString

In [2]: dom1 = parse(r"C:/Users/86155/8first.xml")

In [3]: dom1
Out[3]: <xml.dom.minidom.Document at 0x1e25dbcfa00>

In [4]: fp = open(r"C:/Users/86155/8first.xml", "r", encoding='utf8')

In [5]: dom2 = parse(fp)

In [6]: dom2
Out[6]: <xml.dom.minidom.Document at 0x1e25dbe47c0>

In [7]: fp.close()

In [8]: data = """
    <goods>
        <shirt quality="A">
            <size>170</size>
        </shirt>
    </goods>
"""

In [9]: dom3 = parseString(data)

In [10]: dom3
Out[10]: <xml.dom.minidom.Document at 0x1e25dbe4760>

In [11]: dom3.toxml()
Out[11]: '<?xml version="1.0" ?><goods>\n        <shirt quality="A">\n            <size>170</size>\n        </shirt>\n    </goods>'

In [12]: print(dom3.toxml())
Out[12]: <?xml version="1.0" ?><goods>
        <shirt quality="A">
            <size>170</size>
        </shirt>
    </goods>
    
In [13]: elem = dom3.createElement("element")

In [14]: elem.toxml()
Out[14]: '<element/>'

In [15]: text = dom3.createTextNode("Text date")

In [16]: text.toxml()
Out[16]: 'Text date'

In [17]: attrib = dom3.createAttribute("quality")

In [18]: attrib.name
Out[18]: 'quality'
  1. Node接口
In [1]: from xml.dom.minidom import *

In [2]: dom1 = parse(r"C:/Users/86155/8first.xml")

In [3]: root = dom1.documentElement

In [4]: root
Out[4]: <DOM Element: goods at 0x2978c9c0160>

In [5]: root.nodeType
Out[5]: 1

In [6]: root.ELEMENT_NODE
Out[6]: 1

In [7]: childs = root.childNodes

In [8]: childs
Out[8]: [<DOM Text node "'\n    '">,
 <DOM Element: shirt at 0x2978c9c0ca0>,
 <DOM Text node "'\n    '">,
 <DOM Element: shirt at 0x2978c9ffa60>,
 <DOM Text node "'\n'">]
 
In [9]: shirt = root.childNodes[1]

In [10]: shirt
Out[10]: <DOM Element: shirt at 0x2978c9c0ca0>

In [11]: shirt.parentNode
Out[11]: <DOM Element: goods at 0x2978c9c0160>

In [12]: parent = shirt.parentNode

In [13]: parent == root
Out[13]: True

In [14]: root.firstChild
Out[14]: <DOM Text node "'\n    '">

In [15]: root.lastChild
Out[15]: <DOM Text node "'\n'">

In [16]: shirt.previousSibling
Out[16]: <DOM Text node "'\n    '">

In [17]: shirt.nextSibling
Out[17]: <DOM Text node "'\n    '">

In [18]: attrib = shirt.attributes

In [19]: attrib.items()
Out[19]: [('quality', 'A')]
  1. Element接口
In [20]: shirt.tagName
Out[20]: 'shirt'

In [21]: shirt.getAttribute("quality")
Out[21]: ''

In [22]: print(shirt.toxml())
Out[22]: <shirt>
        	<name>Helen</name>
        	<size>170</size>
        	<quantity>10</quantity>
       	 	<color>black</color>
    	</shirt>
    
In [23]: shirt.setAttribute("quality", "B")

In [24]: print(shirt.toxml())
Out[24]: <shirt quality="B">
        	<name>Helen</name>
        	<size>170</size>
        	<quantity>10</quantity>
        	<color>black</color>
    	</shirt>
  1. Text接口
In [25]: name = shirt.childNodes[1]

In [26]: name.childNodes
Out[26]: [<DOM Text node "'Helen'">]

In [27]: name_text = name.childNodes[0]

In [28]: name_text.data
Out[28]: 'Helen'

在这里插入图片描述

在这里插入图片描述

6.3 对XML文档的操作

  1. 对XML文档的遍历
In [29]: def traversal(node):
    		if not node.childNodes:	# 递归结束条件
        		return
    		for child in node.childNodes:
        		print(child)
        		traversal(child)	# 递归调用
        
In [30]: traversal(root)
		<DOM Text node "'\n    '">
		<DOM Element: shirt at 0x20adeb81dc0>
		<DOM Text node "'\n        '">
		<DOM Element: name at 0x20adebbe940>
		<DOM Text node "'Helen'">
		<DOM Text node "'\n        '">
		<DOM Element: size at 0x20adebbe9d0>
		<DOM Text node "'170'">
		<DOM Text node "'\n        '">
		<DOM Element: quantity at 0x20adebbea60>
		<DOM Text node "'10'">
		<DOM Text node "'\n        '">
		<DOM Element: color at 0x20adebbeaf0>
		<DOM Text node "'black'">
		<DOM Text node "'\n    '">
		<DOM Text node "'\n    '">
		<DOM Element: shirt at 0x20adebbeb80>
		<DOM Text node "'\n        '">
		<DOM Element: name at 0x20adebbec10>
		<DOM Text node "'First'">
		<DOM Text node "'\n        '">
		<DOM Element: size at 0x20adebbeca0>
		<DOM Text node "'175'">
		<DOM Text node "'\n        '">
		<DOM Element: quantity at 0x20adebbed30>
		<DOM Text node "'9'">
		<DOM Text node "'\n        '">
		<DOM Element: color at 0x20adebbedc0>
		<DOM Text node "'white'">
		<DOM Text node "'\n    '">
		<DOM Text node "'\n'">
from xml.dom.minidom import *
dom1 = parse(r"C:/Users/86155/8first.xml")
root = dom1.documentElement
def another_traversal(node):
    if not node.childNodes:
        return

    firstChild = node.firstChild
    next = firstChild
    while next:
        print(next)
        another_traversal(next)
        next = next.nextSibling

if __name__=="__main__":
    another_traversal(root)

运行结果:

<DOM Text node “’\n '”>
<DOM Element: shirt at 0x1aff6e7dd30>
<DOM Text node “’\n '”>
<DOM Element: name at 0x1aff6e978b0>
<DOM Text node “‘Helen’”>
<DOM Text node “’\n '”>
<DOM Element: size at 0x1aff6e97940>
<DOM Text node “‘170’”>
<DOM Text node “’\n '”>
<DOM Element: quantity at 0x1aff6e979d0>
<DOM Text node “‘10’”>
<DOM Text node “’\n '”>
<DOM Element: color at 0x1aff6e97a60>
<DOM Text node “‘black’”>
<DOM Text node “’\n '”>
<DOM Text node “’\n '”>
<DOM Element: shirt at 0x1aff6e97af0>
<DOM Text node “’\n '”>
<DOM Element: name at 0x1aff6e97b80>
<DOM Text node “‘First’”>
<DOM Text node “’\n '”>
<DOM Element: size at 0x1aff6e97c10>
<DOM Text node “‘175’”>
<DOM Text node “’\n '”>
<DOM Element: quantity at 0x1aff6e97ca0>
<DOM Text node “‘9’”>
<DOM Text node “’\n '”>
<DOM Element: color at 0x1aff6e97d30>
<DOM Text node “‘white’”>
<DOM Text node “’\n '”>
<DOM Text node “’\n’”>

  1. 对XML文档的查询
from xml.dom.minidom import *
dom1 = parse(r"C:/Users/86155/8first.xml")
root = dom1.documentElement
def search_by_traversal(node, name):
    if not node.childNodes:
        return
    for child in node.childNodes:
        if child.nodeType == Node.ELEMENT_NODE and child.tagName == name:
            print(child.toxml())
        traversal(child)

if __name__ == "__main__":
    search_by_traversal(root, "color")

运行结果:

black
white

In [31]: root.getElementsByTagName("color")
Out[31]: [<DOM Element: color at 0x20adebbeaf0>, <DOM Element: color at 0x20adebbedc0>]

In [32]: colors = root.getElementsByTagName("color")

In [33]: for color in colors:
    		print(color.toxml())
<color>black</color>
<color>white</color>

In [34]: shirts = root.getElementsByTagName("shirt")

In [35]: shirt1 = shirts[0]

In [36]: color1 = shirt1.getElementsByTagName("color")[0]

In [37]: color1.toxml()
Out[37]: '<color>black</color>'

In [38]: shirt2 = shirts[1]

In [39]: color2 = shirt2.getElementsByTagName("color")[0]

In [40]: color2.toxml()
Out[40]: '<color>white</color>'
  1. 对XML文档的增删改
In [41]: goods = dom1.createElement("goods")

In [42]: goods.toxml()
Out[42]: '<goods/>'

In [43]: test = dom1.createElement("test")

In [44]: text = dom1.createTextNode("This is a text node")

In [45]: text
Out[45]: <DOM Text node "'This is a '...">

In [46]: test.appendChild(text)
Out[46]: <DOM Text node "'This is a '...">

In [47]: goods.appendChild(test)
Out[47]: <DOM Element: test at 0x20adebcfee0>

In [48]: goods
Out[48]: <DOM Element: goods at 0x20adebcfb80>

In [49]: goods.toxml()
Out[49]: '<goods><test>This is a text node</test></goods>'

In [50]: goods.removeChild(test)
Out[50]: <DOM Element: test at 0x20adebcfee0>

In [51]: goods
Out[51]: <DOM Element: goods at 0x20adebcfb80>

In [52]: goods.toxml()
Out[52]: '<goods/>'

In [53]: goods.appendChild(test)
Out[53]: <DOM Element: test at 0x20adebcfee0>

In [54]: goods.toxml()
Out[54]: '<goods><test>This is a text node</test></goods>'

In [55]: test2 = dom1.createElement("test2")

In [56]: goods.replaceChild(test2,test)
Out[56]: <DOM Element: test at 0x20adebcfee0>

In [57]: goods.toxml()
Out[57]: '<goods><test2/></goods>'

In [58]: goods.removeChild(test2)
Out[58]: <DOM Element: test2 at 0x20adebcfd30>

In [59]: shirt = dom1.createElement("shirt")

In [60]: goods.appendChild(shirt)
Out[60]: <DOM Element: shirt at 0x20adebcfca0>

In [61]: shirt.setAttribute("quality", "A")

In [62]: name = dom1.createElement("name")

In [63]: text = dom1.createTextNode("Helen")

In [64]: name.appendChild(text)
Out[64]: <DOM Text node "'Helen'">

In [65]: shirt.appendChild(name)
Out[65]: <DOM Element: name at 0x20adebcfaf0>

In [66]: size = dom1.createElement("size")

In [67]: text = dom1.createTextNode("170")

In [68]: size.appendChild(text)
Out[68]: <DOM Text node "'170'">

In [69]: shirt.appendChild(size)
Out[69]: <DOM Element: size at 0x20adebcfc10>

In [70]: goods.toxml()
Out[70]: '<goods><shirt quality="A"><name>Helen</name><size>170</size></shirt></goods>'

七、习题

习题:

  1. XML文档分为哪两个部分?
  2. 在DTD中使用什么标记声明元素类型?
  3. 使用Python验证下面XML文档,并进行解析,获取每个员工的数据。
<employees>
    <employee id="1">
        <name>张三</name>
        <age>32</age>
        <sex></sex>
        <address>上海</address>
    </employee>
    <employee id="2">
        <name>李四</name>
        <age>22</age>
        <sex></sex>
        <address>北京</address>
    </employee>
</employees>

答案:

  1. 第一部分是XML文档声明,第二部分是处理指令(可省略),第三部分是元素和属性定义。
  2. 使用StringIO生成了一个文件对象。其字符串为一个DTD定义,这里的含义指明了empty元素的类型,这里值必须为空。元素的类型包括4类,EMPTY(空元素)、ANY(任意)、Mixed(混合元素)和Children(子元素)。
  3. 代码如下。
<!--one.dtd-->
<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT employees (employee+)>
<!ELEMENT employee (name,age,sex,address)>
<!ELEMENT name ANY>
<!ELEMENT age ANY>
<!ELEMENT sex ANY>
<!ELEMENT address ANY>
# -*- coding: UTF-8 -*-
import xml.dom.minidom
import xml.etree.ElementTree as ET
from lxml import etree, objectify
from io import StringIO
from xml.dom.minidom import parse



# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse(r"C:/Users/86155/one.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
    print("Root element : %s" % collection.getAttribute("shelf"))

# 在集合中获取所有人员信息
employees = collection.getElementsByTagName("employee")

# 打印每个人的详细信息
for employee in employees:
    print("*****Employee*****")
    if employee.hasAttribute("id"):
        print("Id: %s" % employee.getAttribute("id"))
    name = employee.getElementsByTagName('name')[0]
    print("Name: %s" % name.childNodes[0].data)
    age = employee.getElementsByTagName('age')[0]
    print("Age: %s" % age.childNodes[0].data)
    sex = employee.getElementsByTagName('sex')[0]
    print("Sex: %s" % sex.childNodes[0].data)
    address = employee.getElementsByTagName('address')[0]
    print("Address: %s" % address.childNodes[0].data)


# 文档结构良好性验证
try:
    ET.parse(r"C:/Users/86155/one.xml")
    print("这是一个良构的XML文档")
except Exceptionas as e:
    print("这可能是一个非良构文档")
    print("出错信息:", e)

# 文档的有效性验证
dtd = etree.DTD(open(r"C:/Users/86155/one.dtd"))
xml = objectify.parse(open(r"C:/Users/86155/one.xml", 'rb'))
print(dtd.validate(xml))

运行结果:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值