Как обратиться к значению дочернего элемента текущего узла при выборе другого узла с XPath? (Связанный с DDEX)
Рассмотрим эту XML-структуру, упрощенную версию стандарта DDEX:
<doc>
<master>
<ResourceInfo>
<Name>Foo</Name>
<Seq>1</Seq>
</ResourceInfo>
<ResourceInfo>
<Name>Bar</Name>
<Seq>2</Seq>
</ResourceInfo>
</master>
<track>
<Resource>
<Name>Foo</Name>
</Resource>
</track>
<track>
<Resource>
<Name>Bar</Name>
</Resource>
</track>
</doc>
Я хотел бы выбрать узел ResourceInfo в <master>
с ребенком <Name>
сопоставляя текстовое значение имени каждого из узлов трека, чтобы получить номер Seq.
Я могу сделать это напрямую, получая дерево lxml каждой дорожки и явно запрашивая <ResourceInfo>
вот так:
track.xpath('/doc/master/ResourceInfo/Seq[../Name[text()="Foo"]]')
Но это предполагает, что я знаю название каждого трека и могу явно указать его заранее. Я хотел бы иметь возможность тупо отобразить это и каким-то образом заменить "Foo" в xpath с некоторой ссылкой на имя text()
ресурса текущего трека.
Это своего рода объединение треков и ресурсов на text()
Имени в мастере с text()
имени в каждой дорожке. Есть ли простой способ сделать это с XPath?
Я пытаюсь перебрать каждый трек и вытащить Seq с трека. Поэтому я не могу явно попросить "Foo". Мне нужно самоанализ - "Дайте мне Seq, который является братом <Name>
узел в мастере с сопоставлением значений <Name>
текущего узла в <track>
".
2 ответа
Я не уверен, что я полностью понимаю, но если текущий контекст:
/doc/track/Resource/Name
и вы используете следующий XPath:
/doc/master/ResourceInfo[Name = current()]/Seq
Вы должны получить Seq
из ResourceInfo
того же самого Name
,
Прочитав ваш комментарий, я теперь понимаю, что вы после. Вы можете просто использовать Python для соединения:
from lxml import etree
doc = etree.parse('sample.xml')
# gather resources
resources = {}
for element in doc.xpath('/doc/master/ResourceInfo'):
name = element[0].text
seq = element[1].text
resources[name] = seq
# gather tracks
tracks = []
for element in doc.xpath('/doc/track/Resource/Name'):
name = element.text
tracks.append(name)
# join:
for track in tracks:
print 'Track: %s, seq: %s' % (track, resources.get(track))
# returns:
# Track: Foo, seq: 1
# Track: Bar, seq: 2
Предыдущий ответ:
XML не был правильно сформирован:
<doc>
<master>
<ResourceInfo>
<Name>Foo</Name>
<Seq>1</Seq>
</ResourceInfo>
<ResourceInfo>
<Name>Bar</Name>
<Seq>2</Seq>
</ResourceInfo>
</master>
<track>
<Resource>
<Name>Foo</Name>
</Resource>
</track> <!-- was missing backslash -->
<track>
<Resource>
<Name>Bar</Name>
</Resource>
</track>
</doc>
Ваш код работает:
from lxml import etree
doc = etree.parse('a.xml')
for element in doc.xpath('/doc/master/ResourceInfo/Seq[../Name[text()="Foo"]]'):
#print etree.tostring(element)
print element.text
# returns
# 1