zoukankan      html  css  js  c++  java
  • XML解析(DOM、ElementTree)及转换为JSON

    xml.dom篇

        DOM是Document Object Model的简称,XML 文档的高级树型表示。该模型并非只针对 Python,而是一种普通XML 模型。Python 的 DOM 包是基于 SAX 构建的,并且包括在 Python 2.0 的标准 XML 支持里。

    一、xml.dom的简单介绍

    1、主要方法:

    minidom.parse(filename):加载读取XML文件

    doc.documentElement:获取XML文档对象

    node.getAttribute(AttributeName):获取XML节点属性值

    node.getElementsByTagName(TagName):获取XML节点对象集合

    node.childNodes :返回子节点列表。

    node.childNodes[index].nodeValue:获取XML节点值

    node.firstChild:访问第一个节点,等价于pagexml.childNodes[0]

    返回Node节点的xml表示的文本:

    doc = minidom.parse(filename)

    doc.toxml('UTF-8')

    访问元素属性:

    Node.attributes["id"] 
    a.name #就是上面的 "id" 
    a.value #属性的值  


    2、举例说明

    例1:文件名:book.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <info>
     3     <intro>Book message</intro>
     4     <list id='001'>
     5         <head>bookone</head>
     6         <name>python check</name>
     7         <number>001</number>
     8         <page>200</page>
     9     </list>
    10 
    11     <list id='002'>
    12         <head>booktwo</head>
    13         <name>python learn</name>
    14         <number>002</number>
    15         <page>300</page>
    16     </list>
    17 </info>

    (1)创建DOM对象

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    print(dom1)
    

    返回结果为:

    <xml.dom.minidom.Document object at 0x00000000025CE468>

    (2)获取根字节

    root=dom1.documentElement # 这里得到的是根节点
    print(root)
    print(root.nodeName)
    print(root.nodeValue)
    print(root.nodeType)
    

    返回结果为:

    <DOM Element: info at 0x23619c8>
    info
    None
    1

    其中:

    info是指根节点的名称root.nodeName

    None是指根节点的值root.nodeValue

    1是指根节点的类型root.nodeType,更多节点类型如下表:

    NodeType

    Named Constant

    1

    ELEMENT_NODE

    2

    ATTRIBUTE_NODE

    3

    TEXT_NODE

    4

    CDATA_SECTION_NODE

    5

    ENTITY_REFERENCE_NODE

    6

    ENTITY_NODE

    7

    PROCESSING_INSTRUCTION_NODE

    8

    COMMENT_NODE

    9

    DOCUMENT_NODE

    10

    DOCUMENT_TYPE_NODE

    11

    DOCUMENT_FRAGMENT_NODE

    12

    NOTATION_NODE

    (3)子元素、子节点的访问

    A、返回root子节点列表

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    root=dom1.documentElement
    print(root.childNodes)
    

    运行结果为:

    [<DOM Text node "'    '">, <DOM Element: intro at 0x2255470>, <DOM Text node "'    '">, <DOM Element: list at 0x2255508>, <DOM Text node "'    '">, <DOM Element: list at 0x2255800>, <DOM Text node "' '">]

    for i in root.childNodes:
        print(i)

    结果:

    Text也是一个节点,Text表示两个标签之间的内容,如

    第一行结果表示<info>和<intro>之间的内容,为一个回车和4个空格

    第五行结果表示</list>和<list id='002'>之间的内容,为两个回车和4个空格

      

    B、获取XML节点值,如返回根节点下第一个子节点、第二个子节点intro的值和名字

    print(root.childNodes[0].nodeName)
    print(root.childNodes[0].nodeValue)
    print(root.childNodes[1].nodeName)
    print(root.childNodes[1].nodeValue)
    

    运行结果为:

    可以看出,第一个节点的值是一个回车加4个空格(竖线为鼠标光标)

    C、访问第一个节点

    print(root.firstChild.nodeName)
    

    运行结果为:

    #text

    D、获取已经知道的元素名字的值,如要获取intro后的book message可以使用下面的方法: 

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    root=dom1.documentElement
    node= root.getElementsByTagName('intro')[0]
    for node in node.childNodes:
        if node.nodeType in (node.TEXT_NODE,node.CDATA_SECTION_NODE):
            print(node.data)
    

    这种方法的不足之处是需要对类型进行判断,使用起来不是很方便。运行结果是:

    Book message

    二、XML解析

    对上面的xml进行解析

    方法1 代码如下:

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    root=dom1.documentElement
    booknode=root.getElementsByTagName('list')
    for booklist in booknode:
        print('='*20)
        print('id:'+booklist.getAttribute('id'))
        for nodelist in  booklist.childNodes:
            if nodelist.nodeType ==1:
                print(nodelist.nodeName+':',)
            for node in nodelist.childNodes:
                print(node.data)
    

     

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    root=dom1.documentElement
    # print(root) # <DOM Element: info at 0x2131a60>
    booknode=root.getElementsByTagName('list') # 返回元素列表
    # print(booknode) # [<DOM Element: list at 0x22505a0>, <DOM Element: list at 0x2250898>]
    for booklist in booknode: # 循环列表,booklist表示每本书
        print('='*20)
        print('id:'+booklist.getAttribute('id')) # 标签属性值
        # print(booklist.childNodes) # 每本书的节点,[<DOM Text node "'
            '">, <DOM Element: head at 0x2590638>, <DOM Text node "'
            '">, <DOM Element: name at 0x25906d0>, <DOM Text node "'
            '">, <DOM Element: number at 0x2590768>, <DOM Text node "'
            '">, <DOM Element: page at 0x2590800>, <DOM Text node "'
        '">]
        for nodelist in  booklist.childNodes: # 循环当前书的节点
            if nodelist.nodeType ==1: # 如果节点类型是1,表示是ELEMENT_NODE
                print(nodelist.nodeName+':',end='')
                # print(type(nodelist))
                '''
                上面一句的输出结果
                id:001
                <class 'xml.dom.minidom.Element'>
                <class 'xml.dom.minidom.Element'>
                <class 'xml.dom.minidom.Element'>
                <class 'xml.dom.minidom.Element'>
                '''
                # print(nodelist.childNodes)
                '''
                上面一句的输出结果
                id:001
                [<DOM Text node "'bookone'">]
                [<DOM Text node "'python che'...">]
                [<DOM Text node "'001'">]
                [<DOM Text node "'200'">]
                '''
                for node in nodelist.childNodes:
                    print(node.data)
    

    运行结果为:

    ==================== 
    id:001 
    head: bookone 
    name: python check 
    number: 001 
    page: 200 
    ==================== 
    id:002 
    head: booktwo 
    name: python learn 
    number: 002 
    page: 300

    方法二:

    代码: 

    import xml.dom.minidom
    dom1 = xml.dom.minidom.parse('book.xml')
    root = dom1.documentElement
    booknode = root.getElementsByTagName('list')
    for booklist in booknode:
        print('=' * 20)
        print('id:' + booklist.getAttribute('id'))
        print('head:' + booklist.getElementsByTagName('head')[0].childNodes[0].nodeValue.strip())
        print('name:' + booklist.getElementsByTagName('name')[0].childNodes[0].nodeValue.strip())    
        print('number:' + booklist.getElementsByTagName('number')[0].childNodes[0].nodeValue.strip())
        print('page:' + booklist.getElementsByTagName('page')[0].childNodes[0].nodeValue.strip())
    

    运行结果与方法一一样。比较上面的两个方法,方法一根据xml的树结构进行了多次循环,可读性上不及方法二,方法二直接对每一个节点进行操作,更加清晰。

    为了更加方便程序的调用,可以使用一个list加一个字典进行存储

    xml转换为字典(方法一):

    import xml.dom.minidom
    dom1=xml.dom.minidom.parse('book.xml')
    root=dom1.documentElement
    book=[]
    booknode=root.getElementsByTagName('list')
    for booklist in booknode:
        bookdict={}
        bookdict['id']=booklist.getAttribute('id')
        bookdict['head']=booklist.getElementsByTagName('head')[0].childNodes[0].nodeValue.strip()
        bookdict['name']=booklist.getElementsByTagName('name')[0].childNodes[0].nodeValue.strip()
        bookdict['number']=booklist.getElementsByTagName('number')[0].childNodes[0].nodeValue.strip()
        bookdict['page']=booklist.getElementsByTagName('page')[0].childNodes[0].nodeValue.strip()
        book.append(bookdict)
    print(book)
    

    运行结果为:

    [{'id': '001', 'head': 'bookone', 'name': 'python check', 'number': '001', 'page': '200'}, {'id': '002', 'head': 'booktwo', 'name': 'python learn', 'number': '002', 'page': '300'}]

    该列表里包含了两个字典。

    xml转换为字典(方法二):

     1 <?xml version="1.0"?>  
     2 <root>  
     3     <person age="18">  
     4         <name>张三</name>  
     5         <sex></sex>  
     6     </person>  
     7      <person age="19" des="您好">  
     8         <name>李四</name>  
     9         <sex></sex>  
    10      </person>  
    11 </root>
    from xml.etree import ElementTree as et
    import json
    
    # 从xml文件读取结点 转换为json格式,并保存到文件中
    print('read node from xmlfile, transfer them to json, and save into jsonFile:')
    root1 = et.parse("testXml.xml") # 直接加载文件
    print(root1) # <xml.etree.ElementTree.ElementTree object at 0x00000000023E3D30>
    f = open('testJson.json', 'a', encoding="utf8")
    for each in root1.getiterator("person"): # 利用getiterator方法得到指定节点
        print(each) # <Element 'person' at 0x000000000211C638>, <Element 'person' at 0x00000000025DFC78>
        tempDict = each.attrib # attrib获取XML节点属性值,返回字典
        print(type(tempDict)) # <class 'dict'>
        print(tempDict) # {'age': '18'}, {'age': '19', 'des': '您好'}
        for childNode in each.getchildren(): # 利用getchildren方法得到子节点
            print(childNode) # <Element 'name' at 0x00000000023E3C28>, <Element 'sex' at 0x00000000025BFC28>
            tempDict[childNode.tag] = childNode.text # tag获取节点名,text获取节点值
        print(tempDict) # {'age': '18', 'name': '张三', 'sex': '男'}, {'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}
        # 上面的字典,里面键值都是单引号,dumps后,变成双引号
        tempJson = json.dumps(tempDict, ensure_ascii=False)
        print(tempJson) # {"age": "18", "name": "张三", "sex": "男"}, {"age": "19", "des": "您好", "name": "李四", "sex": "女"}
        f.write(tempJson + "
    ")
    f.close()
    
    # 从json文件中读取,并打印
    print('read json from jsonfile:')
    for eachJson in open('testJson.json', 'r', encoding='utf8'):
        tempStr = json.loads(eachJson)
        print(tempStr) 

    结果:

    read node from xmlfile, transfer them to json, and save into jsonFile:
    <xml.etree.ElementTree.ElementTree object at 0x0000000001E33DD8>
    <Element 'person' at 0x0000000001E1C408>
    <class 'dict'>
    {'age': '18'}
    <Element 'name' at 0x0000000002205C28>
    <Element 'sex' at 0x00000000025DEC28>
    {'age': '18', 'name': '张三', 'sex': '男'}
    {"age": "18", "name": "张三", "sex": "男"}
    <Element 'person' at 0x00000000025DECC8>
    <class 'dict'>
    {'age': '19', 'des': '您好'}
    <Element 'name' at 0x00000000025DED18>
    <Element 'sex' at 0x00000000025DED68>
    {'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}
    {"age": "19", "des": "您好", "name": "李四", "sex": "女"}
    read json from jsonfile:
    {'age': '18', 'name': '张三', 'sex': '男'}
    {'age': '19', 'des': '您好', 'name': '李四', 'sex': '女'}

    三、建立XML文件

    这里用方法三得到的结果,建立一个xml文件。 

    import xml.dom
    def create_element(doc,tag,attr):
        #创建一个元素节点
        elementNode=doc.createElement(tag)
        #创建一个文本节点
        textNode=doc.createTextNode(attr)
        #将文本节点作为元素节点的子节点
        elementNode.appendChild(textNode)
        return elementNode
    
    dom1=xml.dom.getDOMImplementation()#创建文档对象,文档对象用于创建各种节点。
    doc=dom1.createDocument(None,"info",None)
    top_element = doc.documentElement# 得到根节点
    books=[{'id': '001', 'head': 'bookone', 'name': 'python check', 'number': '001', 'page': '200'}, {'id': '002', 'head': 'booktwo', 'name': 'python learn', 'number': '002', 'page': '300'}] for book in books: sNode=doc.createElement('list') sNode.setAttribute('id',str(book['id'])) headNode=create_element(doc,'head',book['head']) nameNode=create_element(doc,'name',book['name']) numberNode=create_element(doc,'number',book['number']) pageNode=create_element(doc,'page',book['page']) sNode.appendChild(headNode) sNode.appendChild(nameNode) sNode.appendChild(pageNode) top_element.appendChild(sNode)# 将遍历的节点添加到根节点下 xmlfile=open('bookdate.xml','w') doc.writexml(xmlfile,addindent=' '*4, newl=' ', encoding='utf-8') xmlfile.close()

    运行后生成bookdate.xml文件,该文件与book.xml一样。

    xml.etree.ElementTree篇

    依然使用例1的例子,对xml进行解析分析。

    1、加载XML

    方法一:直接加载文件 

    import xml.etree.ElementTree
    root=xml.etree.ElementTree.parse('book.xml')
    print(root)
    

    结果:  

    <xml.etree.ElementTree.ElementTree object at 0x00000000022095F8>

    方法二:加载指定字符串

    import xml.etree.ElementTree
    root = xml.etree.ElementTree.fromstring(xmltext)
    

    这里xmltext是指定的字符串。

    2、获取节点

    方法一 利用getiterator方法得到指定节点  

    book_node=root.getiterator("list")
    print(book_node)
    

    结果:

    [<Element 'list' at 0x00000000021E6F98>, <Element 'list' at 0x00000000025EF3B8>]

    方法二 利用getchildren方法得到子节点,如例1中,要得到list下面子节点head的值:

    import xml.etree.ElementTree
    root=xml.etree.ElementTree.parse('book.xml')
    book_node=root.getiterator("list")
    for node in book_node:
        book_node_child=node.getchildren()[0]
        print(book_node_child.tag+':'+book_node_child.text)
    

    运行结果为:

    head:bookone 
    head:booktwo

    方法三 使用find和findall方法

     find方法找到指定的第一个节点: 

    import xml.etree.ElementTree
    root=xml.etree.ElementTree.parse('book.xml')
    book_find=root.find('list')
    # print(book_find) # <Element 'list' at 0x0000000002406F48>
    # print(type(book_find)) # <class 'xml.etree.ElementTree.Element'>
    for note in book_find:
        # print(note)
        '''
        <Element 'head' at 0x00000000025F6B38>
        <Element 'name' at 0x00000000025F6B88>
        <Element 'number' at 0x000000000260A228>
        <Element 'page' at 0x000000000260F368>
        '''
        print(note.tag+':'+note.text)
    

    运行结果:

    head:bookone 
    name:python check 
    number:001 
    page:200

    findall方法将找到指定的所有节点: 

    import xml.etree.ElementTree
    root=xml.etree.ElementTree.parse('book.xml')
    book=root.findall('list')
    print(book) # [<Element 'list' at 0x0000000001E66F48>, <Element 'list' at 0x00000000025DF368>]
    for book_list in book:
        for note in book_list:
            print(note.tag+':'+note.text)
    

    运行结果:

    head:bookone 
    name:python check 
    number:001 
    page:200 
    head:booktwo 
    name:python learn 
    number:002 
    page:300

    3、对book.xml进行解析的实例

    import xml.etree.ElementTree
    root=xml.etree.ElementTree.parse('book.xml')
    book=root.findall('list')
    for book_list in book:
        print('='*20)
        # print(type(book_list.attrib)) # <class 'dict'>
        if 'id' in book_list.attrib:
            print("id:"+book_list.attrib['id'])
        for note in book_list:
            print(note.tag+':'+note.text)
    print('='*20)
    

    运行结果为:

    ==================== 
    id:001 
    head:bookone 
    name:python check 
    number:001 
    page:200 
    ==================== 
    id:002 
    head:booktwo 
    name:python learn 
    number:002 
    page:300 
    ====================

    注意:

    当要获取属性值时,如list id=’001’,用attrib方法。

    当要获取节点值时,如<head>bookone</head>中的bookone用text方法。

    当要获取节点名时,用tag方法。 

    》》》》》参考1:http://www.cnblogs.com/xiaowuyi/archive/2012/10/17/2727912.html

    》》》》》参考2:http://blog.csdn.net/laoyaotask/article/details/41384719

  • 相关阅读:
    day103 跨域请求 与频率访问限制.
    day 102 GIT 的使用方法.
    day 101 天
    day 100天 VUE 父子传值,单页面.
    JS 在元素后插入元素
    JS 网页加载后执行多个函数
    MySQL 一般操作语句
    PHP 通过设置表单元素name属性生成数组
    PHP SQL语气中value必须添加单引号
    PHP 单引号和双引号的区别
  • 原文地址:https://www.cnblogs.com/uncleyong/p/6996162.html
Copyright © 2011-2022 走看看