Мне нужно проанализировать XML файл и построить на основе записи результат из данных. Проблема в том, что XML находится в "общей" форме, поскольку он имеет несколько уровней вложенных элементов "node" , которые представляют собой некоторую структуру данных. Мне нужно динамически создавать записи на основе самого глубокого уровня элемента node. Пример XML и ожидаемого вывода внизу.
Я лучше всего знаком с python ElementTree, поэтому я бы предпочел использовать его, но я просто не могу обернуть голову, чтобы динамически строить выходную запись на основе динамической глубины node. Кроме того, мы не можем предположить, что вложенные узлы будут x уровнями глубокими, поэтому просто hardcoding каждый уровень w/loop невозможен. Есть ли способ разобрать XML и построить вывод на лету?
Некоторые дополнительные примечания:
Приветствуются любые идеи/ввод.
<root>
<node>101
<node>A
<node>PlanA
<node>default
<rate>100.00</rate>
</node>
<node>alternative
<rate>90.00</rate>
</node>
</node>
</node>
</node>
<node>102
<node>B
<node>PlanZZ
<node>Group 1
<node>default
<rate>100.00</rate>
</node>
<node>alternative
<rate>90.00</rate>
</node>
</node>
<node>Group 2
<node>Suba
<node>default
<rate>1.00</rate>
</node>
<node>alternative
<rate>88.00</rate>
</node>
</node>
<node>Subb
<node>default
<rate>200.00</rate>
</node>
<node>alternative
<rate>4.00</rate>
</node>
</node>
</node>
</node>
</node>
</node>
</root>
Результат будет выглядеть следующим образом:
SRV SUB PLAN Group SubGrp DefRate AltRate
101 A PlanA 100 90
102 B PlanB Group1 100 90
102 B PlanB Group2 Suba 1 88
102 B PlanB Group2 Subb 200 4
Вот почему у вас есть метод Element Tree find
с XPath.
class Plan( object ):
def __init__( self ):
self.srv= None
self.sub= None
self.plan= None
self.group= None
self.subgroup= None
self.defrate= None
self.altrate= None
def initFrom( self, other ):
self.srv= other.srv
self.sub= other.sub
self.plan= other.plan
self.group= other.group
self.subgroup= other.subgroup
def __str__( self ):
return "%s %s %s %s %s %s %s" % (
self.srv, self.sub, self.plan, self.group, self.subgroup,
self.defrate, self.altrate )
def setRates( obj, aSearch ):
for rate in aSearch:
if rate.text.strip() == "default":
obj.defrate= rate.find("rate").text.strip()
elif rate.text.strip() == "alternative":
obj.altrate= rate.find("rate").text.strip()
else:
raise Exception( "Unexpected Structure" )
def planIter( doc ):
for topNode in doc.findall( "node" ):
obj= Plan()
obj.srv= topNode.text.strip()
subNode= topNode.find("node")
obj.sub= subNode.text.strip()
planNode= topNode.find("node/node")
obj.plan= planNode.text.strip()
l3= topNode.find("node/node/node")
if l3.text.strip() in ( "default", "alternative" ):
setRates( obj, topNode.findall("node/node/node") )
yield obj
else:
for group in topNode.findall("node/node/node"):
grpObj= Plan()
grpObj.initFrom( obj )
grpObj.group= group.text.strip()
l4= group.find( "node" )
if l4.text.strip() in ( "default", "alternative" ):
setRates( grpObj, group.findall( "node" ) )
yield grpObj
else:
for subgroup in group.findall("node"):
subgrpObj= Plan()
subgrpObj.initFrom( grpObj )
subgrpObj.subgroup= subgroup.text.strip()
setRates( subgrpObj, subgroup.findall("node") )
yield subgrpObj
import xml.etree.ElementTree as xml
doc = xml.XML( doc )
for plan in planIter( doc ):
print plan
Edit
Тот, кто дал вам этот XML-документ, должен найти другую работу. Это The Bad Thing (TM) и указывает на довольно случайное игнорирование того, что означает XML.
Я не слишком хорошо знаком с модулем ElementTree
, но вы должны использовать метод getchildren()
для элемента и рекурсивно анализировать данные до тех пор, пока их не будет больше. Это больше sudo-code, чем что-либо:
def parseXml(root, data):
# INSERT CODE to populate your data object here with the values
# you want from this node
sub_nodes = root.getchildren()
for node in sub_nodes:
parseXml(node, data)
data = {} # I'm guessing you want a dict of some sort here to store the data you parse
parseXml(parse(file).getroot(), data)
# data will be filled and ready to use