2020-1-4(126)

第十二章 json字符串和xml解析
1 json
1.1 json简介
 Json全称:Javasript Object Notation(javascrip对象表示法)
 Json是存储和交换文本信息的语法。类似xml
 Json比xml更小、更快、更易解析
1.2 json语法和语法规则
1、json语法:Json语法是javascrip语法的子集。
2、json语法规则:json语法是javascript对象表示法语法的子集。
 数据在名称/值对中,“name”:“cc” 等价于 name:“cc”
Json值类型可以是:int、float 、str、bool 、数组、对象、null
 数据由逗号分隔
 花括号保存对象
对象可以包含多个名称/值对,比如:{“name”:”cc”,”age”:18}
 方括号保存数组
数组可以包含多个对象,比如:
{
“employees”:[
{“name”:”cc”,”age”:18},
{“name”:”zz”,”age”:20}
]
}
1.3 json编码
1、使用json.dumps()将一个python数据类型列表编码成json格式的字符串。

>>> import json
>>> data=[{"a":"A","b":(2,3),"c":3.3}]
>>> data
[{'a': 'A', 'b': (2, 3), 'c': 3.3}]
>>> type(data)
<class 'list'>
>>> json.dumps(data)
'[{"a": "A", "b": [2, 3], "c": 3.3}]'   #编译为json串后,元组类型改为json数组

2、函数原型:
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True,
cls=None, indent=None, separators=None, encoding=‘utf-8’, default=None,
sort_keys=False, **kw)
3、函数参数如下:
(1) sort_keys:是否按字典排序(a到z)输出,默认False不排序。

>>> import json
>>> data=[{"a":"A","x":[1,2],"f":666}]
>>> json.dumps(data,sort_keys=True)
'[{"a": "A", "f": 666, "x": [1, 2]}]'

(2) indent:

>>> import json
>>> data=[{"a":"A","x":[1,2],"f":666}]
>>> print(json.dumps(data,indent=3))
[
   {
      "a": "A",
      "x": [
         1,
         2
      ],
      "f": 666
   }
]

(3) separators:去掉逗号和冒号后面的空格。不带该参数的结果能看到逗号和冒号后都有个空格,这是为了美化输出结果,但是在传输过程中越精简越好。

>>> data=[{"a":"A","x":[1,2],"f":666}]
>>> json.dumps(data,separators=(",",":"))
'[{"a":"A","x":[1,2],"f":666}]'
>>> data=[{"a":"A","x":[1,2],"f":666}]
>>> len(json.dumps(data))
35
>>> len(json.dumps(data,separators=(",",":")))
29

(4) skipkeys:dict对象的key只能是基本数据类型(str,int,float,bool,None),如果是其他类型,在编码过程中会抛出TypeError异常。该参数默认为False,设置为True可以跳过这些抛出异常的key,不处理。

>>> data=[{"a":"A","x":[1,2],"f":666,(1,2):(1,2)}]
>>> json.dumps(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\App\Python37\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "D:\App\Python37\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "D:\App\Python37\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
TypeError: keys must be str, int, float, bool or None, not tuple
>>> json.dumps(data,skipkeys=True)
'[{"a": "A", "x": [1, 2], "f": 666}]'

(5) ensure_ascii:编码使用的字符集,默认使用ascii编码。设置为False,就会以Unicode进行编码

>>> data=[{"country":"中国","name":"程程"}]
>>> json.dumps(data)
'[{"country": "\\u4e2d\\u56fd", "name": "\\u7a0b\\u7a0b"}]'
>>> json.dumps(data,ensure_ascii=False)
'[{"country": "中国", "name": "程程"}]'

1.4 json解码
将json格式字符串解码为python对象,使用json.loads()。

>>> data=[{"a":"A","x":(1,2),"f":666}] 
>>> data_json=json.dumps(data)      
>>> data_json
'[{"a": "A", "x": [1, 2], "f": 666}]'
>>> data_py=json.loads(data_json)
>>> data_py              #原来是tuple,经过json的编码解码,最终被转为list
[{'a': 'A', 'x': [1, 2], 'f': 666}]

1.5 json串与python数据类型的转换
Python类型  Json类型  Python类型
dict object dict
list tuple array list
str unicode string str unicode
int float Number(int) int float
True False true false True False
None null None

>>> data=[{1:2,"n":"c","a":1.33},[1,2],(3,4),"abc",1,3.3,True,False,None]  #python
>>> data_json=json.dumps(data)
>>> data_json
'[{"1": 2, "n": "c", "a": 1.33}, [1, 2], [3, 4], "abc", 1, 3.3, true, false, null]'  #json
>>> data_py=json.loads(data_json)
>>> data_py
[{'1': 2, 'n': 'c', 'a': 1.33}, [1, 2], [3, 4], 'abc', 1, 3.3, True, False, None]     #python

1.6 将类对象编码成json串
Python中的dict对象可以直接序列化为json的{},但是很多时候,可能用class表示对象,比如定义Employee类,然后直接去序列化就会报错,是因为类不是一个可以直接序列化的对象,但我们可以使用dumps()函数中的default参数来实现。

import json
class Employee:
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender
    def obj_json(self,obj_instance):
        return {
        "name":obj_instance.name,
        "age":obj_instance.age,
        "gender":obj_instance.gender
        }
emp=Employee("cc",18,"女")
print(json.dumps(emp,ensure_ascii=False,default=emp.obj_json))

import json
class Employee:
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender
    def obj_json(self):
        return {
        "name":self.name,
        "age":self.age,
        "gender":self.gender
        }
emp=Employee("cc",18,"女")
print(json.dumps(emp.obj_json(),ensure_ascii=False))

1.7 json反序列化为类对象
使用json.loads()函数中object_hook参数实现。

import json
class Employee:
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender

emp=Employee("cc",18,"女")
def json_to_class(emp):
    return Employee(emp["name"],emp["age"],emp["gender"])

json_str='{"name":"cc","age":18,"gender":"女"}'
e=json.loads(json_str,object_hook=json_to_class)
print(e)
print(e.name)

2 xml
2.1 xml简介

2.2 xml文档(树结构)

2.3 xml基础知识介绍

2.4 xml命名规则

2.5 python解析xml的三种方法
1、SAX
2、DOM
3、ElementTree
2.5.1 xml.dom解析xml
思路:一个DOM的解析器在解析一个xml文档时,一次性读取整个文档,将文档中所有元素保存在内存中的一个树结构里,之后利用DOM提供的不同函数来读取该文档的内容和结构,也可以把修改过的内容写入xml文件。
Xml实例(创建一个book.xml文件,内容如下)

<?xml version="1.0" encoding="utf-8" ?>
<!--this is a test about xml.-->
<booklist type="science and engineering">
  <book category="math">
    <title>learning math</title>
    <author>张三</author>
    <pageNumber>561</pageNumber>
  </book>
  <book category="Python">
    <title>learning Python</title>
    <author>李四</author>
    <pageNumber>600</pageNumber>
  </book>
</booklist>

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

>>> from xml.dom.minidom import parse
>>> dom_tree=parse("d:\\2019\\book.xml")  #打开xml并解析为内存中的一棵树
>>> print(dom_tree)
<xml.dom.minidom.Document object at 0x00000223F1275A68>
>>> print(type(dom_tree))
<class 'xml.dom.minidom.Document'>

(2)获取xml文档对象,就是拿到DOM树的根

>>> booklist=dom_tree.documentElement
>>> print(booklist)
<DOM Element: booklist at 0x223f110b188>

(3)获取xml文档函数doc.toxml(encoding=None)

>>> print(dom_tree.toxml())
<?xml version="1.0" ?><!--this is a test about xml.--><booklist type="science and engineering">
  <book category="math">
    <title>learning math</title>
    <author>张三</author>
    <pageNumber>561</pageNumber>
  </book>
  <book category="Python">
    <title>learning Python</title>
    <author>李四</author>
    <pageNumber>600</pageNumber>
  </book>
</booklist>

(4)判断是否包含属性

>>> if booklist.hasAttribute("type"):性")
...     print("booklist元素存在type属性")
... else:
...     print("booklist元素不存在type属性"))
...
booklist元素存在type属性

(5)获取属性(获取节点node的某个属性的值)

>>> if booklist.hasAttribute("type"):性")")
...     print("Root element is",booklist.getAttribute("type"))
...
Root element is science and engineering

(6)获取节点元素
获取xml文档中某个父节点下具有相同节点名的节点对象,是一个list对象

>>> books=booklist.getElementsByTagName("book")
>>> print(books)
[<DOM Element: book at 0x223f110b548>, <DOM Element: book at 0x223f1290188>]
>>> print(type(books))
<class 'xml.dom.minicompat.NodeList'>

返回节点node下所有子节点组成的list

>>> print(books[0].childNodes)
[<DOM Text node "'\n    '">, <DOM Element: title at 0x223f110bf48>, <DOM Text node "'\n    '">, <DOM Element: author at 0x223f1290048>, <DOM Text node "'\n    '">, <DOM Element: pageNumber at 0x223f12900e8>, <DOM Text node "'\n  '">]
from xml.dom.minidom import parse
#minidom解析器打开xml文档并将其解析为内存中的一棵树
DOMTree = parse("d:\\2019\\book.xml")
print(type(DOMTree))
booklist = DOMTree.documentElement
print(booklist)
print("*"*30)
books = booklist.getElementsByTagName("book")
d={}
for i in range(1,6,2):
    tag_name = books[1].childNodes[i].tagName
    d[tag_name]=books[1].childNodes[i].childNodes[0].data
print(d)
for k,v in d.items():
    print(k,v)

(7)获取节点文本值(获取节点node的文本值,即标签之间的文本内容)

>>> import json
>>> from xml.dom.minidom import parse
>>> dom_tree=parse("d:\\2019\\book.xml")
>>> booklist=dom_tree.documentElement
>>> books=booklist.getElementsByTagName("book")
>>> books.length
2
>>> for book in books:
...     print("********book********")
...     if book.hasAttribute("category"):
...         print("category is",book.getAttribute("category"))
...
********book********
category is math
********book********
category is Python
>>> title=book.getElementsByTagName("title")
>>> title
[<DOM Element: title at 0x265945935e8>]
>>> title=book.getElementsByTagName("title")[0]
>>> title
<DOM Element: title at 0x265945935e8>
>>> title.childNodes[0].data
'learning Python'
>>> author=book.getElementsByTagName("author")[0]
>>> author.childNodes[0].data
'李四'
>>> pageNumber=book.getElementsByTagName("pageNumber")[0]
>>> pageNumber.childNodes[0].data
'600'

(8)判断是否有子节点
判断节点node下是否有子节点,如果有返回True,否则返回False。但需要注意,每个节点都默认有一个文本子节点,所以只要标签后有值,就返回True,只有当标签后没值时并且也没有子节点时才会返回False。

>>> if books[0].hasChildNodes():
...     print("存在子节点",books[0].childNodes)
... else:
...     print("不存在子节点")
...
存在子节点 [<DOM Text node "'\n    '">, <DOM Element: title at 0x26594593368>, <DOM Text node "'\n    '">, <DOM Element: author at 0x26594593408>, <DOM Text node "'\n    '">, <DOM Element: pageNumber at 0x265945934a8>, <DOM Text node "'\n  '">]

2.5.2 xml.dom创建xml文件
1、创建空白文档
doc=Document()
 该方法用于创建一个空白的xml文档对象,并返回这个doc对象
 每个xml文档都是一个Document对象,代表着内存中的DOM树

>>> from xml.dom.minidom import Document
>>> doc=Document()   #在内存中创建一个空的文档
>>> doc
<xml.dom.minidom.Document object at 0x00000265945E1FA8>

2、创建xml文档节点

doc.createElement(tagName)  tagName—生成节点的名称
>>> root=doc.createElement("companys")      #创建根节点companys
>>> root.tagName
'companys'

>>> company=doc.createElement("gloryroad")  #创建子节点gloryroad

>>> name=doc.createElement("Name")        #创建子节点Name
>>> ceo=doc.createElement("CEO")           #创建子节点CEO

3、添加节点属性
Node.setAttribute(attName,value) 给节点添加属性值对,attName—属性名称 value—属性值

>>> root.setAttribute("name","公司列表")    #给根节点root添加属性
>>> company.setAttribute("name","公司1")   #给子节点company添加属性
>>> root.getAttribute("name")
'公司列表'

4、添加文本节点
doc.createTextNode(data)

>>> name_data=doc.createTextNode("光荣之路")
>>> ceo_data=doc.createTextNode("吴老师")
>>> name.appendChild(name_data)
<DOM Text node "'光荣之路'">
>>> ceo.appendChild(ceo_data)
<DOM Text node "'吴老师'">

5、添加子节点
doc/parentNode.appendChild(node)
将节点node添加到文档对象doc作为文档树的根节点或者添加到父节点parentNode下作为其子节点。

>>> doc.appendChild(root)
<DOM Element: companys at 0x26594593f48>
>>> company.appendChild(name)
<DOM Element: Name at 0x265945f7048>
>>> company.appendChild(ceo)
<DOM Element: CEO at 0x265945f7368>
>>> root.appendChild(company)
<DOM Element: gloryroad at 0x265945937c8>

6、生成xml文档
doc.writexml(fp,indent=’’,addindent=’’,newl=’’,encoding=None)
该方法用于将内存中xml文档树写入文件中,并保存到本地磁盘。
fp—文件对象 indent—根节点缩进方式 addindent—子节点缩进方式 newl—换行方式

>>> fp=open("d:\\2019\\school.xml","w",encoding="utf-8")
>>> doc.writexml(fp,indent='',addindent='\t',newl='\n',encoding='utf-8')
>>> fp.close()

7、结果

<?xml version="1.0" encoding="utf-8"?>
<companys name="公司列表">
	<gloryroad name="公司1">
		<Name>光荣之路</Name>
		<CEO>吴老师</CEO>
	</gloryroad>
</companys>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值