将XML元素转换为其JSON等效元素,反之亦然
lxml2json的Python项目详细描述
lxml2json
lxml2json是一个python包,它将xml元素转换为它们的json等价物,反之亦然。 有许多选项可将数据转换为所需格式:
- 重命名标记
- 忽略元素
- 在树中移动元素
- 始终将数据表示为列表
- 提供空元素的值
安装:
pip install lxml2json
用法:
from lxml2json import convert
from pprint import pprint as pp
xml = '''
<parent>
<c1>a</c1>
<c1>b</c1>
<c1>c</c1>
<c2>
<gc1>d</gc1>
<gc2>e</gc2>
<gc3>f</gc3>
</c2>
<c2>
<gc1>g</gc1>
<gc2>h</gc2>
<gc3>i</gc3>
</c2>
<c3>
<gc1>j</gc1>
<gc1>k</gc1>
<gc1>l</gc1>
</c3>
<c4/>
</parent>'''
d = convert(xml)
pp(d)
{'parent': {'c1': ['a', 'b', 'c'],
'c2': [{'gc1': 'd', 'gc2': 'e', 'gc3': 'f'},
{'gc1': 'g', 'gc2': 'h', 'gc3': 'i'}],
'c3': {'gc1': ['j', 'k', 'l']},
'c4': None}}
选项
lxml2json提供以下可选参数来修改转换行为或输出数据格式:
顺序:布尔型,默认为false。指定是否将输出生成为OrderedDict。
备注文本:默认为无。指定给不包含子元素和文本值的元素的值。
始终列表:默认为无。允许将xpath查询的规范应用于将 使所有匹配的元素存储为列表。这对于创建确定性数据结构很有用。 请参见下面的示例。
忽略:默认为无。允许将xpath查询的规范应用于将导致 所有匹配的元素都将被忽略。
重命名:默认为无。允许通过提供元组/元组列表(包含匹配元素的xpath查询)来重命名标记 使用指定所需标记的字符串。例如,请参见下面的内容。
移动:默认为无。提供将元素移动到层次结构中所需位置的选项。用例:扁平化 深深嵌套的结构。需要元组/包含匹配元素的xpath查询的元组列表,以及xpath查询 (相对于匹配元素的位置)移动元素的位置。请参见下面的示例
操作顺序为:移动、重命名、忽略。这允许您通过将子元素移动到同一层次结构级别,重命名原始元素,然后忽略它来基本上用子元素替换元素。
始终列表
lxml2json的处理逻辑总是试图将元素表示为字典,除非有多个 具有相同标记的同级元素,在这种情况下,它必须将对象表示为列表,因为词典需要唯一的键。
这会在整个json数据结构中产生差异,因为xml的某些部分可以表示为列表和 具有相同标记的其他节可以表示为字典或文本值,具体取决于具有相同标记的同级项的数目。
考虑以下示例:
>>> from lxml2json import convert
>>> from pprint import pprint as pp
>>>
>>> xml = '''
... <parent>
... <c1>
... <num>1</num>
... <num>2</num>
... <num>3</num>
... </c1>
... <c2>
... <num>4</num>
... <num>5</num>
... <num>6</num>
... </c2>
... <c3>
... <num>7</num>
... </c3>
... </parent>
... '''
>>>
默认情况下,lxml2json将此xml对象表示为:
>>> pp(convert(xml))
{'parent': {'c1': {'num': ['1', '2', '3']},
'c2': {'num': ['4', '5', '6']},
'c3': {'num': '7'}}}
注意,"num"键的值包含在前两个实例的列表中,但最后一个实例的值只是它的本机值7。 这种行为是预期的,在许多情况下,它的功能和XML结构的表示都非常好。但是,它可以呈现 迭代生成的json对象时遇到的挑战,因为可能需要额外的逻辑来处理值是否包含在列表中。
为了允许更确定的结构,lxml2json允许您提供将应用于输入的xml的xpath查询,从而产生任何匹配的元素 存储为列表,而不考虑相同兄弟标记的数量。
在本例中,xpath查询:"//num"将匹配所有"num"元素,从而使所有此类元素将其值存储在列表中。
让我们看看这一点:
>>>
>>> pp(convert(xml, alwaysList=".//num"))
{'parent': {'c1': {'num': ['1', '2', '3']},
'c2': {'num': ['4', '5', '6']},
'c3': {'num': ['7']}}}
>>>
请注意第三个"num"值现在是一个列表,类似于前两个实例。
您可以提供任意数量的xpath查询,可以是查询列表,也可以是逗号分隔的值字符串。无论哪种情况,都将标记匹配的元素。
忽略
"ignore"选项允许指定要忽略的元素。 例子:
>>> from lxml2json import convert
>>> from pprint import pprint as pp
>>>
xml = '''
<parent>
<son>
<grandson>Thomas</grandson>
<grandson>Robert</grandson>
<granddaughter>Karen</granddaughter>
</son>
</parent>
'''
>>>
>>> pp(convert(xml))
{'parent': {'son': {'granddaughter': 'Karen',
'grandson': ['Thomas', 'Robert']}}}
>>>
>>> pp(convert(xml, ignore=".//granddaughter"))
{'parent': {'son': {'grandson': ['Thomas', 'Robert']}}}
>>>
通过指定xpath查询"//grandaughter",lxml2json将在转换时忽略带有该标记的任何元素。
移动
"move"选项允许数据结构的变异以匹配所需的状态。一个用例是"展平"嵌套结构。
需要提供元组/元组列表,每个元组都包含一个匹配元素的xpath查询以及一个相应的xpath查询(相对于匹配元素的位置),指定层次结构中移动数据的位置。
示例:
xml = """
<children>
<child>
<name>Joey</name>
<age>7</age>
<favorite>
<things>
<toys>
<toy>legos</toy>
<toy>playstation</toy>
<toy>bike</toy>
</toys>
</things>
</favorite>
</child>
</children>"""
#default result
>>> pp(convert(xml))
{'children': {'child': {'age': '7',
'favorite': {'things': {'toys': {'toy': ['legos',
'playstation',
'bike']}}},
'name': 'Joey'}}}
>>>
#perhaps we want a flattened child dictionary
>>> pp(convert(xml, move=(".//toy", "./../../../.."), ignore=".//favorite"))
{'children': {'child': {'age': '7',
'name': 'Joey',
'toy': ['legos', 'playstation', 'bike']}}}
从json转换为xml
lxml2json提供一个"reverse"函数,为输入的dictionary对象生成一个xml元素(或字符串)。
注意:如果输入的字典有多个顶级k:v对,或者顶级键的值是一个列表,那么将创建一个"根"元素,以便 格式化的XML结构,需要一个根元素。
选项
只有一个布尔选项:"text",默认为false。当设置为true时,reverse函数将输出一个打印良好的xml元素字符串。