当我尝试写入文件时,将 JSON 转换为 XML 错误
Posted
技术标签:
【中文标题】当我尝试写入文件时,将 JSON 转换为 XML 错误【英文标题】:Conversion of JSON to XML errors out when I try to write to file 【发布时间】:2021-12-28 22:25:51 【问题描述】:我正在使用 Python 将 JSON 转换为 XML。
我正在演示如何从一个文件 CSV 开始,您可以将其转换为链中的多种格式。所以,CSV 到 JSON,JSON 到 XML,XML 到链中的下一个文件类型,等等,回到 CSV。
我从 Kaggle (https://www.kaggle.com/canggih/anime-data-score-staff-synopsis-and-genre) 获得了一个公共域 CSV 文件,然后将其转换为 JSON。
我正在尝试从 JSON 转换为 XML 并写入输出文件。
我使用这个将 CSV 转换为 JSON(没有格式化,只是直接转换):
#This should convert CSV to JSON
import json, os
import pandas as pd
import csv
df = pd.read_csv('dataanime.csv')
df.to_json(r'sassyg_data_Anime.json')
然后,我创建了我的 JSON 到 XML 文件:
#With help from instructor and CodeSpeedy
#https://www.codespeedy.com/how-to-convert-json-to-xml-using-python/
#Import libraries
import json as j
import xml.etree.ElementTree as et
#load in the json file
with open("sassyg_data_Anime.json") as json_file_format:
d = j.load(json_file_format)
#create the main container element for the entire XML file
r = et.Element("Work")
#creates the subelements for each part of the json file
et.SubElement(r,"Title").text = d["Title"]
et.SubElement(r,"Type").text = d["Type"]
et.SubElement(r,"Episodes").text = d["Episodes"]
et.SubElement(r,"Status").text = d["Status"]
et.SubElement(r,"Start airing").text = str(d["Start airing"])
et.SubElement(r,"End airing").text = str(d["End airing"])
et.SubElement(r,"Starting season").text = d["Starting season"]
et.SubElement(r,"Broadcast time").text = d["Broadcast time"]
et.SubElement(r,"Producers").text = d["Producers"]
et.SubElement(r,"Licensors").text = d["Licensors"]
et.SubElement(r,"Studios").text = d["Studios"]
et.SubElement(r,"Sources").text = d["Sources"]
et.SubElement(r,"Genres").text = d["Genres"]
et.SubElement(r,"Duration").text = str(d["Duration"])
et.SubElement(r,"Rating").text = d["Rating"]
et.SubElement(r,"Score").text = str(d["Score"])
et.SubElement(r,"Scored by").text = str(d["Scored by"])
et.SubElement(r,"Members").text = str(d["Members"])
et.SubElement(r,"Favorites").text = str(d["Favorites"])
et.SubElement(r,"Description").text = d["Description"]
#create the element tree/info for the write file
a = et.ElementTree(r)
#ERROR ERROR
#structure the output for xml via tostring rather than str
#Cannot write an ElementTree to file, errors out
#This was one solution I came up with, still errors out
a_xml_str = et.tostring(a)
print(a_xml_str)
#This might error out as well, I can't get the program to get to this point
#write file it should go to
outfile = open("json_to_xml.xml", 'w', encoding='utf-8')
outfile.write(a_xml_str)
outfile.close()
我得到的错误是:
Traceback (most recent call last):
File "F:\Data_Int_Final\Gardner_json_to_xml\convert_json_to_xml.py", line 44, in <module>
a_xml_str = et.tostring(a)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\xml\etree\ElementTree.py", line 1109, in tostring
ElementTree(element).write(stream, encoding,
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\xml\etree\ElementTree.py", line 748, in write
serialize(write, self._root, qnames, namespaces,
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\xml\etree\ElementTree.py", line 873, in _serialize_xml
tag = elem.tag
AttributeError: 'ElementTree' object has no attribute 'tag'
这是我尝试过的最新版本的代码。谁能看到解决方案?
更新: 我还有另外两种方法可以转换为起始 JSON 文件,其中一种方法会更好吗?
import json
import csv
def make_json(csvFilePath, jsonFilePath):
data =
with open(csvFilePath, encoding='utf-8') as csvf:
csvReader = csv.DictReader(csvf)
for rows in csvReader:
key = rows['Title']
data[key] = rows
with open(jsonFilePath, 'w', encoding='utf-8') as jsonf:
jsonf.write(json.dumps(data, indent=4))
csvFilePath = r'dataanime.csv'
jsonFilePath = r'dataAnime.json'
make_json(csvFilePath, jsonFilePath)
当我使用这个 JSON 文件时,我的 XML 转换出错了:
Traceback (most recent call last):
File "F:\Data_Int_Final\convert_json_to_xml.py", line 16, in <module>
et.SubElement(r,"Title").text = d["Title"]
KeyError: 'Title'
或:
import csv
import json
import time
def csv_to_json(csvFilePath, jsonFilePath):
jsonArray = []
#read csv file
with open(csvFilePath, encoding='utf-8') as csvf:
#load csv file data using csv library's dictionary reader
csvReader = csv.DictReader(csvf)
#convert each csv row into python dict
for row in csvReader:
#add this python dict to json array
jsonArray.append(row)
#convert python jsonArray to JSON String and write to file
with open(jsonFilePath, 'w', encoding='utf-8') as jsonf:
jsonString = json.dumps(jsonArray, indent=4)
jsonf.write(jsonString)
csvFilePath = r'dataanime.csv'
jsonFilePath = r'g_d_anime.json'
start = time.perf_counter()
csv_to_json(csvFilePath, jsonFilePath)
finish = time.perf_counter()
print(f"Conversion of all rows completed successfully in finish - start:0.4f seconds")
当我使用这个创建的 JSON 文件时,我的 XML 转换出错了:
Traceback (most recent call last):
File "F:\Data_Int_Final\convert_json_to_xml.py", line 16, in <module>
et.SubElement(r,"Title").text = d["Title"]
TypeError: list indices must be integers or slices, not str
【问题讨论】:
只是:a_xml_str = et.tostring(r)
我把它切换到(r)
,它的错误是TypeError: write() arguement must be str, not dict
。
如果需要输出,您可以直接从 CSV 转换为 XML 文件。中间 JSON 文件的价值是什么?
我正在演示如何从一个文件 CSV 开始,您可以将其转换为链中的多种格式。所以,CSV 到 JSON,JSON 到 XML,XML 到链中的下一个文件类型,等等,回到 CSV。
在这种情况下,将 CSV 直接转换为 JSON 会创建一个丑陋的 JSON 结构来处理。
【参考方案1】:
使用 CSV 文件并直接从中生成 XML 文件更简单。
试试这样的:
import csv
import xml.etree.ElementTree as et
root = et.Element('WorksXML')
tree = et.ElementTree(root)
with open("dataanime.csv", "r", encoding="utf-8") as fin:
reader = csv.DictReader(fin)
for row in reader:
r = et.SubElement(root, "Work")
# iterate over each of the fields and add to the XML element
for field in reader.fieldnames:
et.SubElement(r, field.replace(' ', '_')).text = row[field]
with open("csv_to_xml.xml", 'wb') as fout:
tree.write(fout, xml_declaration=True, encoding='utf-8')
这会生成一个 XML 文件,其中每个“作品”作为根元素下的单独子元素。
<?xml version="1.0" encoding="utf-8"?>
<WorksXML>
<Work>
<Title>Fullmetal Alchemist: Brotherhood</Title>
<Type>TV</Type>
<Episodes>64</Episodes>
<Status>Finished Airing</Status>
<Start_airing>4/5/2009</Start_airing>
<End_airing>7/4/2010</End_airing>
<Starting_season>Spring</Starting_season>
...
对于 CSV 到 JSON 的转换,第一种方法创建一个以标题为键的字典,第二种方法创建一个数组,其中每个项目都是具有所有属性的对象。
如果任何作品有重复的标题,那么第一种方法将覆盖重复的条目。如果不是,那么这只是您希望如何以字典或列表的形式访问 JSON 文件中的数据的问题。如果您想从 JSON 文件生成 XML,那么使用数组的第二种方法将是更好的选择。
要将基于数组的 JSON 文件转换为 XML,这样就可以完成这项工作。
import json
import xml.etree.ElementTree as ET
def json_to_xml(jsonFilePath, xmlFilePath):
root = ET.Element('WorksXML')
tree = ET.ElementTree(root)
with open(jsonFilePath, "r", encoding="utf-8") as fin:
jdata = json.load(fin)
for obj in jdata:
r = ET.SubElement(root, "Work")
for key, value in obj.items():
ET.SubElement(r, key.replace(' ', '_')).text = value
with open(xmlFilePath, 'wb') as fout:
tree.write(fout, xml_declaration=True, encoding='utf-8')
jsonFilePath = 'g_d_anime.json'
xmlFilePath = 'g_d_anime.xml'
json_to_xml(jsonFilePath, xmlFilePath)
【讨论】:
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 3809: character maps to <undefined>
出错。
很抱歉需要将 encoding="utf-8" 添加到 open("dataanime.csv",...) 行。更新了上面的代码。
行得通,谢谢!以上是关于当我尝试写入文件时,将 JSON 转换为 XML 错误的主要内容,如果未能解决你的问题,请参考以下文章