B
B
beduin012020-12-08 21:38:45
Python
beduin01, 2020-12-08 21:38:45

Why doesn't xpath work on a file?

I can’t understand why xpath finds the value of the tag on the test file, but returns None on the real one:

from lxml import etree

parser = etree.XMLParser(ns_clean=True)
tree = etree.parse('real.xml', parser)
#tree = etree.parse('test.xml', parser)

#print(dir(tree.find("//id")))
print(tree.find("//id").text)

test.xml:
<aa>
<dd></dd>
<foo>
<bar>qqq</bar>
<id>123</id>
</foo>
</aa>


Real XML example:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:export xmlns:ns5="http://zakupki.gov.ru/oos/CPtypes/1" xmlns="http://zakupki.gov.ru/oos/types/1" xmlns:ns6="http://zakupki.gov.ru/oos/pprf615types/1" xmlns:ns7="http://zakupki.gov.ru/oos/EPtypes/1" xmlns:ns8="http://zakupki.gov.ru/oos/printform/1" xmlns:ns9="http://zakupki.gov.ru/oos/control99/1" xmlns:ns2="http://zakupki.gov.ru/oos/export/1" xmlns:ns3="http://zakupki.gov.ru/oos/common/1" xmlns:ns4="http://zakupki.gov.ru/oos/base/1">
    <ns2:fcsNotification111 schemeVersion="9.0">
        <id>18934116</id>
        <purchaseNumber>0373100043519000001</purchaseNumber>
        <docPublishDate>2019-01-11T11:06:05.465+03:00</docPublishDate>
        <docNumber>№0373100043519000001</docNumber>
        <href>http://zakupki.gov.ru/epz/order/notice/inm111/view/common-info.html?regNumber=0373100043519000001</href>
        <printForm>
            <url>http://zakupki.gov.ru/epz/order/notice/printForm/viewXml.html?noticeId=18934116</url>
            <signature type="CAdES-BES"></signature>
        </printForm>
        <purchaseObjectInfo>Теплоснабжение</purchaseObjectInfo>
        <purchaseResponsible>
            <responsibleOrg>
                <regNum>03731000435</regNum>
                <consRegistryNum>001Ч1823</consRegistryNum>
                <fullName>ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ УЧРЕЖДЕНИЕ НАУКИ ИНСТИТУТ ВОДНЫХ ПРОБЛЕМ РОССИЙСКОЙ АКАДЕМИИ НАУК</fullName>
                <postAddress>Российская Федерация, 119333, Москва, УЛ ГУБКИНА, 3</postAddress>
                <factAddress>Российская Федерация, 119333, Москва, УЛ ГУБКИНА, 3</factAddress>
                <INN>7701003690</INN>
                <KPP>773601001</KPP>
            </responsibleOrg>
            <responsibleRole>CU</responsibleRole>
        </purchaseResponsible>
        <placingWay>
            <code>EP111</code>
            <name>Закупка у единственного поставщика (подрядчика, исполнителя) с учетом положений ст. 111 Закона № 44-ФЗ</name>
        </placingWay>
        <lots>
            <lot>
                <lotNumber>1</lotNumber>
                <maxPrice>400000</maxPrice>
                <currency>
                    <code>RUB</code>
                    <name>Российский рубль</name>
                </currency>
                <OKPD2>
                    <code>35.30.11.111</code>
                    <name>Энергия тепловая, отпущенная тепловыми электроцентралями (ТЭЦ)</name>
                </OKPD2>
                <OKPD2>
                    <code>35.30.11.111</code>
                    <name>Энергия тепловая, отпущенная тепловыми электроцентралями (ТЭЦ)</name>
                </OKPD2>
                <purchaseCode>191770100369077360100100100013530000</purchaseCode>
                <tenderPlanInfo>
                    <plan2017Number>2019037310004350010001</plan2017Number>
                    <position2017Number>2019037310004350010000300001</position2017Number>
                </tenderPlanInfo>
                <mustPublicDiscussion>false</mustPublicDiscussion>
            </lot>
        </lots>
        <particularsActProcurement>п.8, ч.1, ст.93 44ФЗ</particularsActProcurement>
    </ns2:fcsNotification111>
</ns2:export>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Vladimir Kuts, 2020-12-08
@beduin01

print(tree.find('.//{http://zakupki.gov.ru/oos/types/1}id').text)
# 18934116

Or this hack:
import re
from lxml import etree

parser = etree.XMLParser(ns_clean=True)
xml = re.sub(' xmlns="[^"]+"', '', xml, count=1) # в xml - ваш реальный xml
tree = etree.fromstring(xml.encode(), parser)

print(tree.find(".//id").text)
# 18934116

I
iddqda, 2020-12-09
@iddqda

because namespaces
to get rid of them I use this method:
https://github.com/jeremyschulman/xml-tutorial/blo...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question