【问题标题】:How to parse and fetch only the desired XML elements from an XML file using python?如何使用 python 从 XML 文件中仅解析和获取所需的 XML 元素?
【发布时间】:2018-08-20 11:03:28
【问题描述】:

我有一个如下所示的 XML 文件:

<rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R5/junos">
    <vlan-information xmlns="http://xml.juniper.net/junos/15.1R5/junos-esw" junos:style="brief">
        <vlan-terse/>
        <vlan>
            <vlan-instance>0</vlan-instance>
            <vlan-name>ACRS-Dev2</vlan-name>
            <vlan-create-time>Fri Jan  1 00:37:59 2010
            </vlan-create-time>
            <vlan-status>Enabled</vlan-status>
            <vlan-owner>static</vlan-owner>
            <vlan-tag>0</vlan-tag>
            <vlan-index>2</vlan-index>
            <vlan-l3-interface>vlan.15 (UP)</vlan-l3-interface>
            <vlan-l3-interface-address>10.8.25.1/24</vlan-l3-interface-address>
            <vlan-protocol-port>Port Mode</vlan-protocol-port>
            <vlan-members-count>7</vlan-members-count>
            <vlan-members-upcount>6</vlan-members-upcount>
        </vlan>
        <vlan>
            <vlan-instance>0</vlan-instance>
            <vlan-name>default</vlan-name>
            <vlan-create-time>Fri Jan  1 00:37:59 2010
            </vlan-create-time>
            <vlan-status>Enabled</vlan-status>
            <vlan-owner>static</vlan-owner>
            <vlan-tag>0</vlan-tag>
            <vlan-index>3</vlan-index>
            <vlan-l3-interface>vlan.11 (UP)</vlan-l3-interface>
            <vlan-l3-interface-address>10.8.27.1/24</vlan-l3-interface-address>
            <vlan-protocol-port>Port Mode</vlan-protocol-port>
            <vlan-members-count>12</vlan-members-count>
            <vlan-members-upcount>2</vlan-members-upcount>
        </vlan>
    </vlan-information>
</rpc-reply>

由此,我只想要 &lt;vlan-name&gt;&lt;vlan-l3-interface-address&gt; 标记,它们将被解析并保存在类似 dict/json 的变量中,其格式为:

{'Vlan-Name' : vlan_name, 'Interface-Address' : interface_addr}

然后为 dicts/json 列表中的每个元素添加这些 dict/json。 这是我在列表中解析和插入 json 的代码:

root = tree.getroot()
nw_pool = []
nw_json = {}
for child in root:
    for items in child:
        for item1 in items:
            if 'vlan-l3-interface-address' in item1.tag:
                interface_addr = item1.text
                nw_json['Interface-Address'] = interface_addr
            elif 'vlan-name' in item1.tag:
                vlan_name = item1.text
                nw_json['Vlan-Name'] = vlan_name
                nw_pool.append(nw_json)
print(nw_pool)

但是当我打印 nw_pool 时,它给了我一个输出,其中重复找到的最后一个元素的 json,而不是给我每个元素的不同 dicts。

输出:

[{'Vlan-Name': 'default', 'Interface-Address': '10.8.27.1/24'}, {'Vlan-Name': 'default', 'Interface-Address': '10.8.27.1/24'}]

而我想要的输出是:

[{'Vlan-Name': 'ACRS-Dev2', 'Interface-Address': '10.8.25.1/24'}, {'Vlan-Name': 'default', 'Interface-Address': '10.8.27.1/24'}] 

有人可以帮我解决这个问题吗?提前致谢。

【问题讨论】:

    标签: python json xml


    【解决方案1】:

    您正在覆盖现有的 dict,而每次迭代都需要一个新的。所以,你需要把nw_json = {}放在另一个地方:

    root = tree.getroot()
    nw_pool = []
    for child in root:
        for items in child:
            nw_json = {}   # Work with new dict
            for item1 in items:
                if 'vlan-l3-interface-address' in item1.tag:
                    interface_addr = item1.text
                    nw_json['Interface-Address'] = interface_addr
                elif 'vlan-name' in item1.tag:
                    vlan_name = item1.text
                    nw_json['Vlan-Name'] = vlan_name
                    nw_pool.append(nw_json)
    print(nw_pool)
    

    【讨论】:

    • 我对您的解决方案的简单性和准确性感到惊讶,先生,我显然错过了。感谢您的时间和帮助。已接受您的回答并 +1。
    • 我的荣幸,编码愉快!
    【解决方案2】:

    您的代码中的问题是您在循环之前启动了 dict() 对象,因此流中的数据已被覆盖。

    @Hoenie's answer 清楚说明您的错误。

    除此之外,我建议您尝试使用 BeautifulSoup 来解析 XML,因为它简单易懂。试试下面的代码。

    from bs4 import BeautifulSoup
    
    fileObj = open('test.xml').read()
    soup = BeautifulSoup(fileObj, 'lxml')
    vlans = soup.findAll('vlan')
    nw_pool = []
    for vlan in vlans:
        nw_json = dict()
        nw_json['Interface-Address'] = vlan.find('vlan-l3-interface-address').text
        nw_json['Vlan-Names'] = vlan.find('vlan-name').text
        nw_pool.append(nw_json)
    print(nw_pool) # O/P [{'Interface-Address': '10.8.25.1/24', 'Vlan-Names': 'ACRS-Dev2'}, {'Interface-Address': '10.8.27.1/24', 'Vlan-Names': 'default'}]
    

    干杯!

    【讨论】:

    • 感谢您的帮助,先生。我不使用 BeautifulSoup 的原因是因为它没有包含在标准库中,并且可能会在稍后投入生产和部署在不同环境中时产生依赖性问题。 +1 为您提供帮助和解决方案 :)
    猜你喜欢
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2014-10-26
    • 1970-01-01
    • 2018-08-27
    相关资源
    最近更新 更多