如何从 python 中的字符串解析 XML
How to parse XML from string in python
我试图从 Python 中的字符串解析 XML 但没有成功。
我要解析的字符串是:
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
</rpc-reply>
我正在尝试使用 xml.etree.ElementTree 库来解析 xml,我还尝试删除与 xml 版本和编码相关的第一行,但没有结果。重现我面临的问题的代码片段是:
import xml.etree.ElementTree as ET
reply_xml='''
<data>
<config>
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
'''
root = ET.fromstring(reply_xml)
for child in root:
print(child.tag, child.attrib)
reply_xml
是一个包含上述 xml 的字符串,因此它应该可以工作,但是如果我使用调试器检查根变量,我发现它没有被正确填充。
似乎第一个 xml 标签 (<?xml version="1.0" encoding="UTF-8"?>
) 产生了一些问题,但即使我手动删除它,我也无法正确解析 xml。
有什么线索可以解析 xml 吗?
您的代码运行良好。它显示根元素的所有子元素,只有 <config> .. </config>
,没有属性。
要到达 <eir>
标签,您应该使用 XPath,或者递归地遍历树。
XPath 的快速解决方案:
root.findall('.//eir')
见下文(1 个带 xpath 的内衬)
import xml.etree.ElementTree as ET
reply_xml='''
<data>
<config>
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>20000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
'''
root = ET.fromstring(reply_xml)
eirs = [e.text for e in root.findall('.//eir')]
print(eirs)
输出
['1000000', '20000000']
您原来的 XML 有命名空间。您需要在 XPath 查询中尊重它们。
import xml.etree.ElementTree as ET
reply_xml '''<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<!-- ... the rest of it ... -->
</config>
</data>
</rpc-reply>'''
ns = {
'calix': 'http://www.calix.com/ns/exa/base'
}
root = ET.fromstring(reply_xml)
for eir in root.findall('.//calix:eir', ns):
print(eir.text)
打印
1000000
10000000
我试图从 Python 中的字符串解析 XML 但没有成功。 我要解析的字符串是:
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
</rpc-reply>
我正在尝试使用 xml.etree.ElementTree 库来解析 xml,我还尝试删除与 xml 版本和编码相关的第一行,但没有结果。重现我面临的问题的代码片段是:
import xml.etree.ElementTree as ET
reply_xml='''
<data>
<config>
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>10000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
'''
root = ET.fromstring(reply_xml)
for child in root:
print(child.tag, child.attrib)
reply_xml
是一个包含上述 xml 的字符串,因此它应该可以工作,但是如果我使用调试器检查根变量,我发现它没有被正确填充。
似乎第一个 xml 标签 (<?xml version="1.0" encoding="UTF-8"?>
) 产生了一些问题,但即使我手动删除它,我也无法正确解析 xml。
有什么线索可以解析 xml 吗?
您的代码运行良好。它显示根元素的所有子元素,只有 <config> .. </config>
,没有属性。
要到达 <eir>
标签,您应该使用 XPath,或者递归地遍历树。
XPath 的快速解决方案:
root.findall('.//eir')
见下文(1 个带 xpath 的内衬)
import xml.etree.ElementTree as ET
reply_xml='''
<data>
<config>
<profile>
<policy-map>
<name>ELINE_PM_1</name>
<class-map-ethernet>
<name>Eth-match-any-1</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>1000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
<policy-map>
<name>ELINE_PM_2</name>
<class-map-ethernet>
<name>Eth-match-any-2</name>
<ingress>
<meter-type>meter-mef</meter-type>
<eir>20000000</eir>
</ingress>
</class-map-ethernet>
</policy-map>
</profile>
</config>
</data>
'''
root = ET.fromstring(reply_xml)
eirs = [e.text for e in root.findall('.//eir')]
print(eirs)
输出
['1000000', '20000000']
您原来的 XML 有命名空间。您需要在 XPath 查询中尊重它们。
import xml.etree.ElementTree as ET
reply_xml '''<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:573a453c-72c0-4185-8c54-9010593dd102">
<data>
<config xmlns="http://www.calix.com/ns/exa/base">
<!-- ... the rest of it ... -->
</config>
</data>
</rpc-reply>'''
ns = {
'calix': 'http://www.calix.com/ns/exa/base'
}
root = ET.fromstring(reply_xml)
for eir in root.findall('.//calix:eir', ns):
print(eir.text)
打印
1000000 10000000