为了使用 python 将 XML 转换为 JSON,存在几种方法,它们通常归结为相同的原理。今天引用最多的方法是 xmltodict。
我正在尝试将多个 xml 文档转换为 JSON,但是如果在某些文档中重复的元素出现一次,则会遇到问题:在这些情况下,生成的不是列表而是对象。这种不一致会导致在例如 spark 中摄取 JSON 时出现问题,它无法再推断 json 元素的模式(该元素是列表还是字符串?)并将其转换为字符串。我们怎样才能最好地解决这个问题?理想情况下,解析器将采用模式(XSD)并“学习”元素可以是无界的,因此应该是一个列表,即使它们是单独的。
- 有没有使用 XSD 将 XML 转换为 JSON 的方法?
- 是否有其他可能的解决方法?例如,我正在考虑将每个非列表项放入列表中,但这会产生开销。
这是一些显示问题的代码
import xmltodict
from lxml import etree
xml1="""<?xml version="1.0" encoding="UTF-8"?>
<a xmlns="https://some.com/ns" xsi:schemaLocation="https://some.com/ns schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><b>x</b></a>
"""
xml2="""<?xml version="1.0" encoding="UTF-8"?>
<a xmlns="https://some.com/ns" xsi:schemaLocation="https://some.com/ns schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><b>x</b><b>y</b></a>
"""
xsd="""<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="https://some.com/ns" targetNamespace="https://some.com/ns" elementFormDefault="qualified" attributeFormDefault="qualified" version="2.4">
<xs:element name="a" type="aType"/>
<xs:complexType name="aType">
<xs:sequence>
<xs:element name="b" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
"""
print(json.dumps(xmltodict.parse(xml1),indent=True))
print(json.dumps(xmltodict.parse(xml2),indent=True))
xmlschema_doc = etree.fromstring(xsd.encode())
xmlschema = etree.XMLSchema(xmlschema_doc)
xml1_doc = etree.fromstring(xml1.encode())
print(etree.tostring(xml1_doc))
result1 = xmlschema.validate(xml1_doc)
print("validation xml1: ")
print(result1)
xml2_doc = etree.fromstring(xml2.encode())
result2 = xmlschema.validate(xml2_doc)
print("validation xml2: ")
print(result2)
将 xml1 输出为 JSON:
{
"a": {
"@xmlns": "https://some.com/ns",
"@xsi:schemaLocation": "https://some.com/ns schema.xsd",
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"b": "x"
}
}
对于 xml2
{
"a": {
"@xmlns": "https://some.com/ns",
"@xsi:schemaLocation": "https://some.com/ns schema.xsd",
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"b": [
"x",
"y"
]
}
}
解决方法可能是:
def nestit(path, key, value):
# don't nest lists. also dont nest attributes.
if type(value) == list or key[:1]=='@':
return key, value
else:
return key, [value]
print(json.dumps(xmltodict.parse(xml1,postprocessor=nestit),indent=True))
生成:
{
"a": [
{
"@xmlns": "https://some.com/ns",
"@xsi:schemaLocation": "https://some.com/ns schema.xsd",
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"b": [
"x"
]
}
]
}
但是对于从不重复的元素,在非常复杂的 xml 结构中效率会降低。