当我尝试写入文件时,将 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 &lt;undefined&gt; 出错。 很抱歉需要将 encoding="utf-8" 添加到 open("dataanime.csv",...) 行。更新了上面的代码。 行得通,谢谢!

以上是关于当我尝试写入文件时,将 JSON 转换为 XML 错误的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 响应转换为 Json 时出错

将 Json 转换为 Xml 的最简单方法

在转换为 XML 之前更改 JSON 对象中的属性名称

Json 将字符串中的 & 转换为 \u0026

PHP - xml到json转换:“无法将字符串解析为XML”

将文本文件转换为干净的 JSON 格式