XML DOM 节点树(笔记)

XML DOM 节点树

XML DOM 把 XML 文档视为一种树结构。这种树结构被称为节点树

可通过这棵树访问所有节点。可以修改或删除它们的内容,也可以创建新的元素。

这颗节点树展示了节点的集合,以及它们之间的联系。这棵树从根节点开始,然后在树的最低层级向文本节点长出枝条:

在这里插入图片描述

<!--   Copyright w3school.com.cn  -->
<!--  W3School.com.cn bookstore example  -->
<bookstore>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="web" cover="paperback">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
</bookstore>

父、子和同级节点

节点树中的节点彼此之间都有等级关系。

父、子和同级节点用于描述这种关系。父节点拥有子节点,位于相同层级上的子节点称为同级节点(兄弟或姐妹)。

  • 在节点树中,顶端的节点成为根节点
  • 根节点之外的每个节点都有一个父节点
  • 节点可以有任何数量的子节点
  • 叶子是没有子节点的节点
  • 同级节点是拥有相同父节点的节点

下面的图片展示出节点树的一个部分,以及节点间的关系:
在这里插入图片描述

第一个子节点 - 最后一个子节点

请看下面的 XML 片段:

<bookstore>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title> 
    <author>J K. Rowling</author> 
    <year>2005</year> 
    <price>29.99</price> 
  </book>
</bookstore>

在上面的 XML 中,<title>元素是<book> 元素的第一个子节点,而<price>元素是<book> 元素的最后一个子节点。

此外,<book>元素是<title><author><year> 以及<price> 元素的父节点。

Python编程

  • 导入DOM库,使用parse解析器打开xml文档,并将其解析为DOM文档,也就是内存中的一棵树,并得到这个对象

    import xml.dom.minidom
    dom = xml.dom.minidom.parse("aligned_by_kyle_1.0.osm")  
    # 拿到DOM的根
    root = dom.documentElement
    
  • 获取带有指定标签名称的所有元素

    getElementsByTagName(name)获取xml文档中的某个父节点下具有相同节点名的节点对象的集合。返回的是list
    代码示例:

    bb = root.getElementsByTagName('node')
    print type(bb)
    print bb[0]
    b = bb[0]
    print b.nodeName
    print b.nodeValue
    
  • 判断是否包含属性值hasAttribute(name)

    from xml.dom.minidom import parse
    #minidom解析器打开xml文档并将其解析为内存中的一棵树
    DOMTree=parse(r'book.xml')
    #获取xml文档对象,就是拿到树的根
    booklist=DOMTree.documentElement
    print('DOM树的根对象:',booklist)
    if booklist.hasAttribute('type'):
          #判断根节点booklist是否有type属性
          print('booklist 元素存在type属性')
    else:
          print('booklist 元素不存在type属性!!!')
    
    if booklist.getElementsByTagName('book')[0].hasAttribute('category'):
          #判断第一个book节点是否有category属性
          print('第一个book节点存在category属性')
    else:
          print('第一个book节点不存在category属性!!!')
    
  • 根据名字获取节点属性值getAttribute(name)

    #coding: utf-8
    import xml.dom.minidom
    dom = xml.dom.minidom.parse("aligned_by_kyle_1.0.osm")  
    
    root = dom.documentElement
    itemlist = root.getElementsByTagName('node')
    item = itemlist[0]
    print item.getAttribute("id")
    print item.getAttribute("lat")
    print item.getAttribute("lon")
    
  • node.childNodes:返回节点node下所有的子节点组成的list

    from xml.dom.minidom import parse
    
    #minidom解析器打开xml文档并将其解析为内存中的一棵树
    DOMTree=parse(r'book.xml')
    #获取xml文档对象,就是拿到树的根
    booklist=DOMTree.documentElement
    #获取booklist对象中所有book节点的list集合
    books=booklist.getElementsByTagName('book')
    
    print('第一个book元素的所有子节点:',books[0].childNodes)
    
  • 获取标签属性

    #coding: utf-8
    import xml.dom.minidom
    dom = xml.dom.minidom.parse("aligned_by_kyle_1.0.osm")  #打开xml文档
    
    root = dom.documentElement              #得到xml文档对象
    print "nodeName:", root.nodeName        #每一个结点都有它的nodeName,nodeValue,nodeType属性
    print "nodeValue:", root.nodeValue      #nodeValue是结点的值,只对文本结点有效
    print "nodeType:", root.nodeType
    print "ELEMENT_NODE:", root.ELEMENT_NODE
    
  • node.hasChildNodes():判断是否有子节点

    from xml.dom.minidom import parse
    
    #minidom解析器打开xml文档并将其解析为内存中的一棵树
    DOMTree=parse(r'book.xml')
    #获取xml文档对象,就是拿到树的根
    booklist=DOMTree.documentElement
    if booklist.hasAttribute('type'):
          #判断根节点booklist是否有type属性,有则获取并打印属性值
          print('Root element is ',booklist.getAttribute('type'))
    
    #获取booklist对象中所有的book节点的list集合
    books=booklist.getElementsByTagName('book')
    print('book节点的个数为:',books.length)
    print ()
    
    if books[0].hasChildNodes():
          print('存在子节点:',books[0].childNodes)
    else:
           print('不存在子节点')
    
  • 获取节点的文本值

    from xml.dom.minidom import parse
    #minidom解析器打开xml文档并将其解析为内存中的一棵树
    DOMTree=parse(r'book.xml')
    #获取xml文档对象,就是拿到树的根
    booklist=DOMTree.documentElement
    
    if booklist.hasAttribute('type'):
          #判断根节点booklist是否有type属性,有则获取并打印属性值
          print('Root element is ',booklist.getAttribute('type'))
    
    #获取booklist对象中所有的book节点的list集合
    books=booklist.getElementsByTagName('book')
    print('book节点的个数为:',len(books))
    print('book节点的个数为:',books.length)
    print ()
    
    for book in books:
          print ("*******************book*******************")
          if book.hasAttribute('category'):
                 print ('category is ',book.getAttribute('category'))
          #根据节点名title/author/pageNumber得到这些节点的集合list
          title=book.getElementsByTagName('title')[0]
          author=book.getElementsByTagName('author')[0]
          pageNumber=book.getElementsByTagName('pageNumber')[0]
    
          print ('title is ',title.childNodes[0].data)
          print ('author is ',author.childNodes[0].data)
          print ('pageNumber is ',pageNumber.childNodes[0].data)
    
  • 修改节点属性的值

    x = node.getAttributeNode("lat")
    x.nodeValue = str(1000.99)
    
  • 创建/修改XML文件的demo

    # -*- coding: utf-8 -*-
    
    import xml.dom.minidom as minidom
    
    doc = minidom.Document()                       # 创建根节点
    a = minidom.getDOMImplementation()
    
    data = doc.createElement('data')               # 在doc中创建一个data标签
    doc.appendChild(data)                          # 将data标签添加到doc中
    data_msg = doc.createTextNode('我是data')       # 在doc中创建一个text文本
    data.appendChild(data_msg)                     # 将text添加到data中
    data.setAttribute('code', '0')                 # 给data标签添加/修改属性(属性名,属性值)
    data.setAttribute('name', 'query_zfy_info')    # 给data标签添加/修改属性(属性名,属性值)
    
    message = doc.createElement('message')         # 在doc中创建一个message标签
    data.appendChild(message)                      # 将message标签添加到父标签data中
    message_data = doc.createTextNode('请求失败')   # 在doc中创建一个text文本
    message.appendChild(message_data)              # 将text文本添加到message_data标签中
    message.setAttribute('a', '2')                 # 给message标签添加/修改属性(属性名,属性值)
    
    person1 = doc.createElement('老王')            # 在doc中创建一个person1标签
    message.appendChild(person1)                  # 将person1标签添加到父标签message中
    person1_info = doc.createTextNode('生平事迹')  # 在doc中创建一个person1_info文本
    person1.appendChild(person1_info)             # 将person1_info文本添加到person1中
    person1.setAttribute('b','1')                 # 设置person1的属性
    
    # 1.创建根节点  2.创建节点  3.给这个节点添加文本  4.设置属性  5.给这个节点添加父节点
    # 将DOM对象写入文件
    xml_path = './03.xml'
    f = open(xml_path, 'w')  
    doc.writexml(writer=f, indent='\t', newl='\n', addindent='\t', encoding='utf-8')
    f.close() 
    # 1、writer是文件对象
    # 2、indent是每个tag前填充的字符,如:’ ‘,则表示每个tag前有两个空格
    # 3、addindent是每个子结点的缩近字符
    # 4、newl是每个tag后填充的字符,如:’\n’,则表示每个tag后面有一个回车
    # 5、encoding是生成的XML信息头中的encoding属性值,在输出时minidom并不真正进行编码的处理,如果你保存的文本内容中有汉字,则需要自已进行编码转换。
    
    
    <?xml version="1.0" encoding="utf-8"?>
    	<data code="0" name="query_zfy_info">
    		我是data
    		<message a="2">
    			请求失败
    			<老王 b="1">生平事迹</老王>
    		</message>
    	</data>
    
  • 尽量使用with...as写入文件

    如果不用with语句,代码如下:

    file = open("/tmp/foo.txt")
    data = file.read()
    file.close()
    

    考虑到可能会保存异常

    file = open("/tmp/foo.txt")
    try:
        data = file.read()
    finally:
        file.close()
    

    虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

    with open("/tmp/foo.txt") as file:
        data = file.read()
    

    具体到python+DOM写入文件:

    # 保存修改到xml文件中
    with open("./WriteTest.xml", 'w') as fh:
        # 4.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
        # 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
        doc.writexml(fh)
        print('恭喜,写入成功!')
    
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值