提问人:Fey010 提问时间:5/5/2023 更新时间:5/5/2023 访问量:46
使用空 findall 结果枚举
Enumerate with empty findall result
问:
我有一个 xml 文件,我想从中计算一些名为“neighbor”的标签。更具体地说,我只想计算邻居标签,它们是任何国家标签的直接子标签。
以下是我的 xml 文件的内容:
<?xml version="1.0"?>
<data>
<country name="Austria">
<rank>1</rank>
<year>2008</year>
<neighbor name="Liechtenstein"/>
<neighbor name="Switzerland"/>
<neighbor name="Italy"/>
</country>
<country name="Iceland">
<hasnoneighbors/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<neighbor name="Malaysia"/>
<someothertag>
<neighbor name="Germany"/>
</someothertag>
</country>
<neighbor name="Jupiter"/>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<neighbor name="Costa Rica"/>
<neighbor name="Colombia"/>
<country name="SubCountry">
<rank>12</rank>
<year>2023</year>
<neighbor name="NeighborOfSubCountry"/>
</country>
</country>
</data>
预期结果应为 7。德国和木星应该被排除在总共 9 个标签之外。
我写了下面一段代码:
import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
totalneighbors = 0
neighborlist = []
for country in root.iter('country'):
print(f'Country {country.attrib["name"]} contains these neighbors:')
for index, neighbor in enumerate(country.findall('neighbor')):
neighborname = neighbor.attrib['name']
print(f'neighbor no {index+1}, with name {neighbor.attrib["name"]}')
neighborlist.append(neighbor.attrib['name'])
print(f"total for this country is {index+1}\n")
totalneighbors += index+1
print(f'total nr of neighbors in country-nodes is {totalneighbors} according to index-counting')
print(f"but the neighborlist says it's {len(neighborlist)}")
我想使用 python 的枚举功能计算标签,但它给了我错误的结果(10 而不是 7)。我在代码中采用了另一种计数方法,将“findall”结果添加到列表中,然后使用该列表的长度。这确实给了我正确的数字。
在代码中添加了一些打印语句后,我弄清楚了哪里出了问题;冰岛没有邻居,但 print-statement 显示该指数仍为 3。看起来好像上一个循环中的索引从未被重置,它只是再次使用那个 3,即使“findall”应该什么也找不到。
所以我的问题是:我做错了什么?为什么当“findall”一无所获时,“enumerate”不给我 0?我用错了吗?还是与空搜索结果结合使用时是不可能的?
我希望有人能澄清这里出了什么问题。
答:
正如你所说,问题在于冰岛没有邻居。第一个国家/地区有三个邻居,因此在运行第一个循环后,其值为 2。但是该循环不会对冰岛执行,因为findall返回一个空列表。因此,该值仍将具有前一个国家/地区的值。index
for
index
您可以在循环之前设置 to。这样,您的代码就可以正常工作。因为如果该国没有邻居,则不会添加任何内容。index
-1
for
totalneighbors
# ...
print(f'Country {country.attrib["name"]} contains these neighbors:')
index = -1
for index, neighbor in enumerate(country.findall('neighbor')):
# remiander of the code
但总的来说,我建议使用软件包和 XPath。
在这里,您可以找到文档:https://lxml.de/parsing.htmllxml
出于您的目的,使用 XPath 是最佳选择。您可以在此处找到更多信息:https://www.w3schools.com/xml/xpath_intro.asp
使用的代码如下所示:lxml
from lxml import etree
root = etree.parse("/path/to/file.xml")
neighbors = root.findall(".//country/neighbor") # this xpath finds all the neighbors exactly after country
希望这会有所帮助。
评论
lxml
index
-1
for
enumerate
评论