предаване на аргумент от низ към Xpath

Наистина съм на загуба от това. Опитвам се да търся в текстовите полета на етикета с данни „MF22“ от xml файл, използвайки xpath и съдържа. Работи добре, когато включа низа за търсене директно във функцията съдържа. Но когато се опитам да го предам като аргумент, той връща всичко във файла.

from lxml import etree as ElementTree
ET = ElementTree.parse('USFLMEO_USSHARE_60200.txt')

bcnIDstr = "AB"
test1 = ET.xpath("//MF22[text()[contains(.,bcnIDstr)]]")
print 'found ' + str(len(test1)) + ' packets'

test2 = ET.xpath("//MF22[text()[contains(.,'AB')]]")
print 'found ' + str(len(test2)) + ' packets'

for elem in test1:
    packet = elem.getparent()
    for elem2 in packet:
        print elem2.tag, elem2.text 

Така че в горния код „test2“ намира всички правилни елементи, но „test1“ не. XML данни по-долу.

<?xml version="1.0" ?>
<topMessage>
    <header dest="366Z" orig="USFLMEO" number="60200" date="2015-10-02T00:00:59.000000000Z" />
    <message>
        <packetsMessage>
            <packet>
                <MF6>324</MF6>
                <MF11>3669</MF11>
                <MF71>2</MF71>
                <MF22>9C634E2AB509240</MF22>
                <MF77>FFFE2FCE31A7155A849207E5B34027500004</MF77>
                <MF67>15 275 0000 40.147870</MF67>
                <MF68>406033830.154</MF68>
                <MF69>0.000000</MF69>
                <MF70>99999.999</MF70>
                <MF72>45.1169</MF72>
                <MF73>399.987</MF73>
                <MF74>0000</MF74>
            </packet>
            <packet>
                <MF6>318</MF6>
                <MF11>3669</MF11>
                <MF71>1</MF71>
                <MF22>9C634E2AB509240</MF22>
                <MF77>FFFE2FCE31A7155A849207E5B34027500004</MF77>
                <MF67>15 275 0000 40.147850</MF67>
                <MF68>406033830.673</MF68>
                <MF69>0.000000</MF69>
                <MF70>99999.999</MF70>
                <MF72>40.0184</MF72>
                <MF73>400.066</MF73>
                <MF74>0000</MF74>
            </packet>
            <packet>
                <MF6>324</MF6>
                <MF11>3669</MF11>
                <MF71>2</MF71>
                <MF22>9C02BE29630F0A0</MF22>
                <MF77>FFFE2FCE015F14B18785039DABCE5A4EC14F</MF77>
                <MF67>15 275 0000 42.922460</MF67>
                <MF68>406033518.783</MF68>
                <MF69>0.000000</MF69>
                <MF70>99999.999</MF70>
                <MF72>41.5108</MF72>
                <MF73>400.053</MF73>
                <MF74>0000</MF74>
            </packet>
            <packet>
                <MF6>315</MF6>
                <MF11>3669</MF11>
                <MF71>3</MF71>
                <MF22>9C02BE29630F0A0</MF22>
                <MF77>FFFE2FCE015F14B18785039DABCE5A4EC14F</MF77>
                <MF67>15 275 0000 42.924905</MF67>
                <MF68>406038122.646</MF68>
                <MF69>0.000000</MF69>
                <MF70>99999.999</MF70>
                <MF72>41.0458</MF72>
                <MF73>399.815</MF73>
                <MF74>0000</MF74>
            </packet>
        </packetsMessage>
    </message>
</topMessage>

Благодаря предварително!


person Jesse Reich    schedule 11.12.2015    source източник
comment
Също така, все още съм много нов в xml и python, така че, моля, не се колебайте да ми разкъсате нов за всичко, което бих могъл да направя по-добър начин.   -  person Jesse Reich    schedule 11.12.2015
comment
Току що го намерих. Кълна се, че търсих един час за това; трябваше да търсим час и 5 минути! Отговорено тук правилният код е test1 = ET.xpath('//MF22[text()[contains(.,"%s")]]' % bcnIDstr)   -  person Jesse Reich    schedule 11.12.2015


Отговори (2)


Просто не сте свързали променливата bcnIDstr в XPath низ

test1 = ET.xpath("//MF22[text()[contains(.,'"+bcnIDstr+"')]]")

Нещо повече, вашият XPath може да бъде съкратен:

test1 = ET.xpath("//MF22[contains(.,'"+bcnIDstr+"')]")

Като алтернатива можете да форматирате низ:

test1 = ET.xpath("//MF22[text()[contains(.,'{0}')]]".format(bcnIDstr))
test1 = ET.xpath("//MF22[contains(.,'{0}')]".format(bcnIDstr))
person Parfait    schedule 11.12.2015
comment
Благодаря! Вие не само ми помогнахте да реша този проблем, вие също помогнахте с друг проблем, който възникна... създаване и предаване на „MF22“ като променлива към израза XPath. Това ме подлудяваше и не мога да го обясня, но очевидно { } не се нуждае от „ “, когато не е в метода съдържа – следният код работи packets = ET.xpath("//{}[contains(.,'{}')]".format(searchtag,bcnIDstr)) - person Jesse Reich; 11.12.2015
comment
Това не проработи при мен! Вместо това използвах '%s и след това % variable_name и това проработи. Но не и с това! Също така изглежда, че използването на $може също да свърши работа. - person M.K; 11.07.2019
comment
Моля, задайте отделен въпрос. Модулният оператор, %, за форматиране на низ е не се препоръчва в Python за str.format. Имаме нужда от контекст за вашата ситуация. - person Parfait; 11.07.2019

Има lxml специфична функция за препратка към променлива на python от XPath:

bcnIDstr = "AB"
test1 = ET.xpath("//MF22[text()[contains(.,$foo)]]", foo=bcnIDstr)

документация: http://lxml.de/xpathxslt.html#the-xpath-method

Това може да бъде полезно, особено когато искате да препратите към променлива на python, съдържаща различен от низ, т.е. XML елемент, в който случай не можете да използвате операция с низ с променливата на python. Това е един пример за такъв случай: Няма вложени възли. Как да получите една информация и след това съответно допълнителна?

person har07    schedule 11.12.2015