2015-02-21 5 views
0

Я пытаюсь выбрать узел в XML на основе других узлов здесь образец моего XMLвыбрать XML-узлов на основе значения другого в питона XPath

<?xml version="1.0"?> 
<gameList> 
    <game> 
     <name>Cave Story</name> 
     <lastplayed>1</lastplayed> 
    </game> 
    <game> 
     <name>Doom</name> 
     <lastplayed>2</lastplayed> 
    </game> 
    <game> 
     <name>Duke Nukem 3D</name> 
    </game> 
</gameList> 

Я уже получил код, чтобы найти самый высокий значение для <lastplayed> и сохраните его как самое новое, но я борюсь с XPath, чтобы получить имя, которое соответствует. Я использую Python, и я должен думать, что XPath будет

//gameList/game/[lastplayed=newest]/name" 

, но когда я пытаюсь получить это выводить в питона оно не похоже на работу.

import lxml.etree as ET 
root = ET.parse("./gamelist.xml") 
newest = 2 
gname = root.xpath(".//gamelist/game/[lastplayed=newest]/name") 

На данный момент я получаю XPathEvalError: Invalid expression.

Я чувствую, что есть что-то маленькое, что мне не хватает, почему это не работает для меня.

Примечание: Для упрощения я объявил новейший вручную, но это будет сделано некоторым кодирование, что у меня уже есть на месте, и этот XML-документ не переодеваться из другой программы, так что я не могу изменить порядок записей

ответ

0

Есть две проблемы с вашей попытки:

  • newest в выражении XPath не является динамическим; он не подключен к переменной newest в вашем коде.

  • Вы используете синтаксис для поиска атрибута в теге, а не для текстового содержимого в тег.

Таким образом вы ищете что-то с атрибутом lastplayed, равной newest. Нет таких совпадений, и ваше выражение неполно.

Для соответствия lastplayed элементов с определенным текстом используйте [lastplayed/text()="specific text"]. Вам нужно будет использовать форматирование строк Python, чтобы получить значение newest в это выражение. Вы ищете матч родственного здесь, поэтому выберите родительский элемент, где текстовый дочерний элемент соответствует: (! Регистрозависимому)

root.xpath(".//game[lastplayed/text()='{}']/name/text()".format(newest)) 

Я оставил в gameList корень, нет необходимости ограничивать поиск корня здесь.

Таким образом, для элементов <game> есть дочерний элемент <lastplayed> с вашим конкретным текстом. Найдя, он выбирает <name> дочерний элемент, принимая текст из этого тега:

>>> import lxml.etree as ET 
>>> sample = '''\ 
... <?xml version="1.0"?> 
... <gameList> 
...  <game> 
...   <name>Cave Story</name> 
...   <lastplayed>1</lastplayed> 
...  </game> 
...  <game> 
...   <name>Doom</name> 
...   <lastplayed>2</lastplayed> 
...  </game> 
...  <game> 
...   <name>Duke Nukem 3D</name> 
...  </game> 
... </gameList> 
... ''' 
>>> root = ET.fromstring(sample) 
>>> root.xpath(".//game[lastplayed/text()='{}']/name/text()".format(newest)) 
['Doom'] 
+0

Это большое спасибо, что решили мою проблему спасибо –

Смежные вопросы