передача строкового аргумента в Xpath

Я действительно в недоумении по этому поводу. Я пытаюсь выполнить поиск по текстовым полям тега данных «MF22» из файла xml, используя xpath и содержит. Он отлично работает, когда я включаю строку поиска непосредственно в функцию contains. Но когда я пытаюсь передать его в качестве аргумента, он возвращает все в файле.

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. Это сводило меня с ума, и я не могу это объяснить, но, по-видимому, { } не нуждается в ' ', если его нет в методе contains - следующий код работал packets = ET.xpath("//{}[contains(.,'{}')]".format(searchtag,bcnIDstr)) - person Jesse Reich; 11.12.2015
comment
Это не сработало для меня! Вместо этого я использовал '%s, а затем % variable_name, и это сработало. Но не с этим! Я также, кажется, использую $might, также выполняю эту работу. - person M.K; 11.07.2019
comment
Пожалуйста, задайте отдельный вопрос. Оператор по модулю % для форматирования строк не рекомендуется использовать в Python для str.format. Нам нужен контекст вашей ситуации. - person Parfait; 11.07.2019