Цикл с условиями через файл XML с использованием lxml etree - PullRequest
1 голос
/ 25 сентября 2011

Интересно, можно ли сделать условные инструкции, связанные с оператором tree.findall ("...") в библиотеке lxml?

У меня есть следующая структура xml в файле

    <sss version="1.2">
    <date>2011-09-23</date>
    <time>12:32:29</time>
    <origin>OPST</origin>
    <user></user>
    <survey>
        <name>Test</name>
        <version>2011-09-02 15:50:10</version>
        <record ident="A">
            <variable ident="10" type="quantity">
                <name>no_v</name>
                <label>Another question</label>
                <position start="23" finish="24"/>
                <values>
                    <range from="0" to="32"/>
                </values>
            </variable>
            <variable ident="11" type="quantity">
                <name>v_683</name>
                <label>another totally another Question</label>
                <position start="25" finish="26"/>
                <values>
                    <range from="0" to="33"/>
                </values>
            </variable>
            <variable ident="12" type="quantity">
                <name>v_684</name>
                <label>And once more Question</label>
                <position start="27" finish="29"/>
                <values>
                    <range from="0" to="122"/>
                </values>
            </variable>
            <variable ident="20" type="single">
                <name>v_684</name>
                <label>Question with alternatives</label>
                <position start="73" finish="73"/>
                <values>
                    <range from="1" to="6"/>
                    <value code="1">Alternative 1</value>
                    <value code="2">Alternative 2</value>
                    <value code="3">Alternative 3</value>
                    <value code="6">Alternative 4</value>
                </values>
            </variable>
        </record>
    </survey>
</sss>

Что я хочу сделать сейчас, так это получить только опрос / запись / переменная / имя .text и опрос / запись / переменная / значения / значение .text, если имя начинается с "v _"

пока у меня есть первая часть

from lxml import etree as ET
tree = ET.parse('scheme.xml')
[elem.text for elem in tree.getiterator(tag='name') if elem.text.startswith('v_')]

Но как я могу получить опрос / запись / переменную / значения / значение .text того же элемента ... и использовать survey / record / variable / name .textкак фильтр?Большое спасибо!

1 Ответ

2 голосов
/ 25 сентября 2011
[(elem.text,elem.getparent().xpath('values/value/text()')) 
 for elem in tree.getiterator(tag='name') if elem.text.startswith('v_')]

выходы

[('v_683', []),
 ('v_684', []),
 ('v_684',
  ['Alternative 1', 'Alternative 2', 'Alternative 3', 'Alternative 4'])]

elem является элементом name. Таким образом, чтобы получить связанные значения, вы можете сначала найти его родителя (variable), затем найти values child, а затем value subchild элементов.


Альтернатива, которая удаляет вызов getparent, но использует немного более сложный XPath:

[(elem.text,elem.xpath('following-sibling::values/value/text()')) for elem in tree.getiterator(tag='name')  if elem.text.startswith('v_')]

following-sibling:: говорит xpath сгенерировать всех братьев и сестер name.

following-sibling::values говорит xpath генерировать всех братьев и сестер из name, которые являются values элементами.

...