为什么 Elementtree 遍历每个元素,即使它不是子元素?
Why is Elementtree iterating over each element even though it isn't a child?
我创建了一个模型,该模型用于创建一个对象,其中包含从 xml 文件收集的数据,使用 ElementTree 解析 xml 文件。我的项目有几千行代码,但我能够使用以下示例快速重现我的问题。
示例 XML 数据:
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
型号:
class neighbor(object):
name = ""
direction = ""
class neighborList(object):
neighbor = []
class country(object):
name = ""
rank = ""
year = ""
gdppc = ""
neighborList = neighborList()
class countryList(object):
country = []
class data(object):
countryList = countryList()
解析器:
from xml.etree import ElementTree as ET
import countries_model as ctry
def CountriesCrusher(filename):
xmldoc = ET.parse(filename)
element = xmldoc.getroot()
_data = ctry
_countryList = ctry.countryList()
for firstLevel in element.findall('country'):
b = ctry.country()
b.rank = firstLevel.find('rank').text
b.year = firstLevel.find('year').text
b.gdppc = firstLevel.find('gdppc').text
b.neighborList = ctry.neighborList()
for secondLevel in firstLevel.findall('neighbor'):
c = ctry.neighbor
c.direction = secondLevel.attrib.get('direction')
c.name = secondLevel.attrib.get('name')
b.neighborList.neighbor.append(c)
_countryList.country.append(b)
a = ctry.data()
a.countryList = _countryList
_data = a
return _data
ictry = CountriesCrusher('countries.xml')
在我 运行 之前,我希望如果我查看 ictry.countryList.country
我会看到三个条目,如果我查看 ictry.countryList.country[0].neighborList.neighbor
我会看到两个相邻条目country 但我看到的是整个 xml 文件中的所有五个相邻元素。为什么会这样??
您没有使用 class country
的实例属性。
像这样写你的 country
class(和所有其他人):
class country:
def __init__(self):
self.name = ""
self.rank = ""
self.year = ""
self.gdppc = ""
self.neighborList = neighborList()
现在 b = ctry.country()
将为您提供一个实例,其属性将是 decoupled/separate 来自对 b = ctry.country()
的第二次调用。您当前的方法 ctry.country
的所有实例都共享相同的属性,因为它们是 class 属性,而不是实例属性。
详细了解 class vs instance attributes here。
我创建了一个模型,该模型用于创建一个对象,其中包含从 xml 文件收集的数据,使用 ElementTree 解析 xml 文件。我的项目有几千行代码,但我能够使用以下示例快速重现我的问题。
示例 XML 数据:
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
型号:
class neighbor(object):
name = ""
direction = ""
class neighborList(object):
neighbor = []
class country(object):
name = ""
rank = ""
year = ""
gdppc = ""
neighborList = neighborList()
class countryList(object):
country = []
class data(object):
countryList = countryList()
解析器:
from xml.etree import ElementTree as ET
import countries_model as ctry
def CountriesCrusher(filename):
xmldoc = ET.parse(filename)
element = xmldoc.getroot()
_data = ctry
_countryList = ctry.countryList()
for firstLevel in element.findall('country'):
b = ctry.country()
b.rank = firstLevel.find('rank').text
b.year = firstLevel.find('year').text
b.gdppc = firstLevel.find('gdppc').text
b.neighborList = ctry.neighborList()
for secondLevel in firstLevel.findall('neighbor'):
c = ctry.neighbor
c.direction = secondLevel.attrib.get('direction')
c.name = secondLevel.attrib.get('name')
b.neighborList.neighbor.append(c)
_countryList.country.append(b)
a = ctry.data()
a.countryList = _countryList
_data = a
return _data
ictry = CountriesCrusher('countries.xml')
在我 运行 之前,我希望如果我查看 ictry.countryList.country
我会看到三个条目,如果我查看 ictry.countryList.country[0].neighborList.neighbor
我会看到两个相邻条目country 但我看到的是整个 xml 文件中的所有五个相邻元素。为什么会这样??
您没有使用 class country
的实例属性。
像这样写你的 country
class(和所有其他人):
class country:
def __init__(self):
self.name = ""
self.rank = ""
self.year = ""
self.gdppc = ""
self.neighborList = neighborList()
现在 b = ctry.country()
将为您提供一个实例,其属性将是 decoupled/separate 来自对 b = ctry.country()
的第二次调用。您当前的方法 ctry.country
的所有实例都共享相同的属性,因为它们是 class 属性,而不是实例属性。
详细了解 class vs instance attributes here。