有时,我们需要将其他格式数据转换为xml,例如把书籍信息csv文件转换成xml:
books.csv:
书名, 作者, 出版社, 价格
精通scrapy网络爬虫, 刘硕, 清华大学出版社, 46.00
...
books.xml:
<Data>
<Book>
<书名>精通scrapy网络爬虫</书名>
<作者>刘硕</作者>
<出版社>清华大学出版社</出版社>
<价格>46.00</价格>
</Book>
...
<Data>
要求:将csv文件转换成xml。
解决方案:
使用标准库中的xml.etree.ElementTree
类,构建ElementTree,然后调用write()
方法写入文件。
- 对于
xml.tree.ElementTree
类:
ElementTree
提供了两个对象:ElementTree
和Element
ElementTree
:将整个xml转化为树,对整个xml文档进行操作(读取,写入,查找等)一般在ElementTree层面进行。
Element
:代表树上单个节点,对单个xml元素及其子元素进行操作,则是在Element层面进行。
- 构建xml:
>>> import xml.etree.ElementTree as ET
>>> data = ET.Element('Data')
>>> book = ET.Element('Book')
>>> autor = ET.Element('作者')
>>> book.set('x', 'abc') #设置属性,与get对应
>>> autor.text = '刘硕'
>>> data.append(book) #为data设置子节点
>>> book.append(autor) #为book设置子节点
>>> ET.dump(data)
<Data><Book x="abc"><作者>刘硕</作者></Book></Data>
>>> et = ET.ElementTree(data)
>>> et
<xml.etree.ElementTree.ElementTree object at 0x7fe39ac381d0>
>>> et.write('test.xml', encoding='utf8') #写入文件
# cat test.xml
<?xml version='1.0' encoding='utf8'?>
<Data><Book x="abc"><作者>刘硕</作者></Book></Data>
设置子节点还可以使用ET.SubElement()
方法,例如book = ET.Element('Book')
data.append(book)
等价于book = ET.SubElement(data, 'Book')
- 方案示例:
books.csv:
书名, 作者, 出版社, 价格
精通scrapy网络爬虫, 刘硕, 清华大学出版社, 46.00
算法导论, Charles E.Leiserson, 人民邮电出版社, 85.00
Python灰帽子, Justin Seitz, 电子工业出版社, 39.00
精通scrapy网络爬虫1, 刘硕, 清华大学出版社, 46.00
算法导论1, Charles E.Leiserson, 人民邮电出版社, 85.00
Python灰帽子1, Justin Seitz, 电子工业出版社, 39.00
精通scrapy网络爬虫2, 刘硕, 清华大学出版社, 46.00
算法导论2, Charles E.Leiserson, 人民邮电出版社, 85.00
Python灰帽子2, Justin Seitz, 电子工业出版社, 39.00
精通scrapy网络爬虫3, 刘硕, 清华大学出版社, 46.00
算法导论3, Charles E.Leiserson, 人民邮电出版社, 85.00
Python灰帽子3, Justin Seitz, 电子工业出版社, 39.00
import csv
from xml.etree.ElementTree import ElementTree, Element, SubElement
def csv_to_xml(csv_path, xml_path):
with open(csv_path) as f:
reader = csv.reader(f)
headers = next(reader)
root = Element('Data')
root.text = '\n\t'
root.tail = '\n'
for row in reader:
book = SubElement(root, 'Book')
book.text = '\n\t\t'
book.tail = '\n\t'
for tag, text in zip(headers, row):
e = SubElement(book, tag)
e.text = text
e.tail = '\n\t\t'
e.tail = '\n\t'
book.tail = '\n'
ElementTree(root).write(xml_path, encoding='utf8')
csv_to_xml('books.csv', 'books.xml')
books.xml:
<?xml version='1.0' encoding='utf8'?>
<Data>
<Book>
<书名>精通scrapy网络爬虫</书名>
<作者>刘硕</作者>
<出版社>清华大学出版社</出版社>
<价格>46.00</价格>
</Book>
<Book>
<书名>算法导论</书名>
<作者>Charles E.Leiserson</作者>
<出版社>人民邮电出版社</出版社>
<价格>85.00</价格>
</Book>
<Book>
<书名>Python灰帽子</书名>
<作者>Justin Seitz</作者>
<出版社>电子工业出版社</出版社>
<价格>39.00</价格>
</Book>
<Book>
<书名>精通scrapy网络爬虫1</书名>
<作者>刘硕</作者>
<出版社>清华大学出版社</出版社>
<价格>46.00</价格>
</Book>
<Book>
<书名>算法导论1</书名>
<作者>Charles E.Leiserson</作者>
<出版社>人民邮电出版社</出版社>
<价格>85.00</价格>
</Book>
<Book>
<书名>Python灰帽子1</书名>
<作者>Justin Seitz</作者>
<出版社>电子工业出版社</出版社>
<价格>39.00</价格>
</Book>
<Book>
<书名>精通scrapy网络爬虫2</书名>
<作者>刘硕</作者>
<出版社>清华大学出版社</出版社>
<价格>46.00</价格>
</Book>
<Book>
<书名>算法导论2</书名>
<作者>Charles E.Leiserson</作者>
<出版社>人民邮电出版社</出版社>
<价格>85.00</价格>
</Book>
<Book>
<书名>Python灰帽子2</书名>
<作者>Justin Seitz</作者>
<出版社>电子工业出版社</出版社>
<价格>39.00</价格>
</Book>
<Book>
<书名>精通scrapy网络爬虫3</书名>
<作者>刘硕</作者>
<出版社>清华大学出版社</出版社>
<价格>46.00</价格>
</Book>
<Book>
<书名>算法导论3</书名>
<作者>Charles E.Leiserson</作者>
<出版社>人民邮电出版社</出版社>
<价格>85.00</价格>
</Book>
<Book>
<书名>Python灰帽子3</书名>
<作者>Justin Seitz</作者>
<出版社>电子工业出版社</出版社>
<价格>39.00</价格>
</Book>
</Data>