使用 ElementTree 解析 XML 文件
Parsing an XML file using ElementTree
我在解析 XML 文件时遇到两个问题。我只想 return 一组属性,即第一个进程下的 属性 值,我想 return 第二个进程下的第二个源。当我使用我的代码时,它 return 是第一个源下的源和第二个源下的第一个源,但我无法将第二个源设为 return。
XML 文件如下所示:
<!-- The description of the process -->
<Description>"This is a description"</Description>
<!-- info on process to be run -->
<Process expectFailure="false">
<Code>Import</Code>
<Sources>
<Source>"Test Data"</Source>
</Sources>
<Destination>Buffered</Destination>
<Properties>
<Property code="format" value="CC"/>
<Property code="Input" value="10N"/>
<Property code="Method" value="BASIC"/>
<Ppoperty code="Resolution" value="5"/>
<Property code="Convention" value="LEFT"/>
<Property code="Bounding" value="BUFFERED"/>
</Properties>
</Process>
<!-- info on second process to be run (compare) -->
<Process>
<Code>SurfaceCompare</Code>
<Sources>
<Source>expectedOutput</Source>
<Source>Buffered</Source>
</Sources>
<Properties>
<Property code="compare_designated" value="true"/>
<Property code="compare_metadata" value="true"/>
<Property code="metadata_type" value="OTHER"/>
</Properties>
</Process>
代码看起来像
from xml.etree import ElementTree
tree = ElementTree.parse("XML_example.xml")
description = tree.findtext("Description")
print(description)
for process in tree.findall('Process'):
for source in process.findall('Sources'):
source_text = source.findtext('Source')
print(source_text)
#returns everything
for property in process.iter('Property'):
print(property.attrib.get('code'))
print(property.attrib.get('value'))
for process in tree.findall('Process'):
for source in process.findall('Sources'):
source = source.findtext('Source')
print(source)
我已经尝试了很多不同的方法来使用 findall、find、iter、get、getiter 方法。我确定我错过了什么,但这是漫长的一天,对于我的一生,我看不到我错过了什么。
也可以更改 XML 的设置方式,但我知道一定有办法解决这个问题,这让我很头疼。
源的正确输出示例:
"Test Data"
expectedOutput
buffered
属性的正确输出示例 1:
format
CC
Input
10N
Method
BASIC
Convention
LEFT
Bounding
BUFFERED
示例正确输出 2:
compare_designated
true
compare_metadata
true
metadata_type
OTHER
实现你想要的最简单的方法是使用 find
或 findall
和 path, iter 与 tag 名称配合使用效果很好,但在您的情况下,使用 path 会更合适。
这是一种方法,顺便说一句,您的示例缺少 root 元素,因此我在代码中添加了:
import xml.etree.ElementTree as ET
from StringIO import StringIO
s = '''<!-- The description of the process -->
<Description>"This is a description"</Description>
<!-- info on process to be run -->
<Process expectFailure="false">
<Code>Import</Code>
<Sources>
<Source>"Test Data"</Source>
</Sources>
<Destination>Buffered</Destination>
<Properties>
<Property code="format" value="CC"/>
<Property code="Input" value="10N"/>
<Property code="Method" value="BASIC"/>
<Ppoperty code="Resolution" value="5"/>
<Property code="Convention" value="LEFT"/>
<Property code="Bounding" value="BUFFERED"/>
</Properties>
</Process>
<!-- info on second process to be run (compare) -->
<Process>
<Code>SurfaceCompare</Code>
<Sources>
<Source>expectedOutput</Source>
<Source>Buffered</Source>
</Sources>
<Properties>
<Property code="compare_designated" value="true"/>
<Property code="compare_metadata" value="true"/>
<Property code="metadata_type" value="OTHER"/>
</Properties>
</Process>'''
# once you've parsed the file, you need to **getroot()**
tree = ET.parse(StringIO('<root>' + s + '</root>')).getroot()
例如可以使用path从第一个Process[1] -> Properties -> 属性获取,使用findall
可以获取到所有 属性 节点,并迭代它们:
# and iterate all Property nodes, and get their attributes like this
for p in tree.findall('./Process[1]/Properties/Property'):
print p.attrib # to get code/value, use p.attrib.get('code') etc.
这样就得到了第一个Process/Properties和所有属性的属性:
{'code': 'format', 'value': 'CC'}
{'code': 'Input', 'value': '10N'}
{'code': 'Method', 'value': 'BASIC'}
{'code': 'Convention', 'value': 'LEFT'}
{'code': 'Bounding', 'value': 'BUFFERED'}
另一个例子,只得到第二个 Process,第二个 Source 文本,使用 path 也非常直接 find
:
print tree.find('./Process[2]/Sources/Source[2]').text
Buffered
我希望你知道如何使用它们,记得获取单个节点你使用 find
,到 return 节点列表,你使用 findall
,希望这有帮助。
我在解析 XML 文件时遇到两个问题。我只想 return 一组属性,即第一个进程下的 属性 值,我想 return 第二个进程下的第二个源。当我使用我的代码时,它 return 是第一个源下的源和第二个源下的第一个源,但我无法将第二个源设为 return。
XML 文件如下所示:
<!-- The description of the process -->
<Description>"This is a description"</Description>
<!-- info on process to be run -->
<Process expectFailure="false">
<Code>Import</Code>
<Sources>
<Source>"Test Data"</Source>
</Sources>
<Destination>Buffered</Destination>
<Properties>
<Property code="format" value="CC"/>
<Property code="Input" value="10N"/>
<Property code="Method" value="BASIC"/>
<Ppoperty code="Resolution" value="5"/>
<Property code="Convention" value="LEFT"/>
<Property code="Bounding" value="BUFFERED"/>
</Properties>
</Process>
<!-- info on second process to be run (compare) -->
<Process>
<Code>SurfaceCompare</Code>
<Sources>
<Source>expectedOutput</Source>
<Source>Buffered</Source>
</Sources>
<Properties>
<Property code="compare_designated" value="true"/>
<Property code="compare_metadata" value="true"/>
<Property code="metadata_type" value="OTHER"/>
</Properties>
</Process>
代码看起来像
from xml.etree import ElementTree
tree = ElementTree.parse("XML_example.xml")
description = tree.findtext("Description")
print(description)
for process in tree.findall('Process'):
for source in process.findall('Sources'):
source_text = source.findtext('Source')
print(source_text)
#returns everything
for property in process.iter('Property'):
print(property.attrib.get('code'))
print(property.attrib.get('value'))
for process in tree.findall('Process'):
for source in process.findall('Sources'):
source = source.findtext('Source')
print(source)
我已经尝试了很多不同的方法来使用 findall、find、iter、get、getiter 方法。我确定我错过了什么,但这是漫长的一天,对于我的一生,我看不到我错过了什么。
也可以更改 XML 的设置方式,但我知道一定有办法解决这个问题,这让我很头疼。
源的正确输出示例:
"Test Data"
expectedOutput
buffered
属性的正确输出示例 1:
format
CC
Input
10N
Method
BASIC
Convention
LEFT
Bounding
BUFFERED
示例正确输出 2:
compare_designated
true
compare_metadata
true
metadata_type
OTHER
实现你想要的最简单的方法是使用 find
或 findall
和 path, iter 与 tag 名称配合使用效果很好,但在您的情况下,使用 path 会更合适。
这是一种方法,顺便说一句,您的示例缺少 root 元素,因此我在代码中添加了:
import xml.etree.ElementTree as ET
from StringIO import StringIO
s = '''<!-- The description of the process -->
<Description>"This is a description"</Description>
<!-- info on process to be run -->
<Process expectFailure="false">
<Code>Import</Code>
<Sources>
<Source>"Test Data"</Source>
</Sources>
<Destination>Buffered</Destination>
<Properties>
<Property code="format" value="CC"/>
<Property code="Input" value="10N"/>
<Property code="Method" value="BASIC"/>
<Ppoperty code="Resolution" value="5"/>
<Property code="Convention" value="LEFT"/>
<Property code="Bounding" value="BUFFERED"/>
</Properties>
</Process>
<!-- info on second process to be run (compare) -->
<Process>
<Code>SurfaceCompare</Code>
<Sources>
<Source>expectedOutput</Source>
<Source>Buffered</Source>
</Sources>
<Properties>
<Property code="compare_designated" value="true"/>
<Property code="compare_metadata" value="true"/>
<Property code="metadata_type" value="OTHER"/>
</Properties>
</Process>'''
# once you've parsed the file, you need to **getroot()**
tree = ET.parse(StringIO('<root>' + s + '</root>')).getroot()
例如可以使用path从第一个Process[1] -> Properties -> 属性获取,使用findall
可以获取到所有 属性 节点,并迭代它们:
# and iterate all Property nodes, and get their attributes like this
for p in tree.findall('./Process[1]/Properties/Property'):
print p.attrib # to get code/value, use p.attrib.get('code') etc.
这样就得到了第一个Process/Properties和所有属性的属性:
{'code': 'format', 'value': 'CC'}
{'code': 'Input', 'value': '10N'}
{'code': 'Method', 'value': 'BASIC'}
{'code': 'Convention', 'value': 'LEFT'}
{'code': 'Bounding', 'value': 'BUFFERED'}
另一个例子,只得到第二个 Process,第二个 Source 文本,使用 path 也非常直接 find
:
print tree.find('./Process[2]/Sources/Source[2]').text
Buffered
我希望你知道如何使用它们,记得获取单个节点你使用 find
,到 return 节点列表,你使用 findall
,希望这有帮助。