Как использовать xpath из lxml на пустых узлах имен? - PullRequest
7 голосов
/ 03 августа 2011

Каков наилучший способ справиться с отсутствием пространства имен на некоторых узлах в XML-документе с использованием lxml? Должен ли я сначала изменить все узлы без имен, чтобы добавить имя «gmd», а затем изменить атрибуты дерева на имя http://www.isotc211.org/2005/gmd как «gmd»? Если так, есть ли чистый способ сделать это с помощью lxml или чего-то еще, что было бы относительно чисто / безопасно?

from lxml import etree
nsmap = charts_tree.nsmap
nsmap.pop(None) # complains without this on the xpath with
# TypeError: empty namespace prefix is not supported in XPath
len (charts_tree.xpath('//*/gml:Polygon',namespaces=nsmap))
# 1180
len (charts_tree.xpath('//*/DS_DataSet',namespaces=nsmap))
# 0 ... Bummer!
len (charts_tree.xpath('//*/DS_DataSet'))
# 0 ... Also a bummer

например. http://www.charts.noaa.gov/ENCs/ENCProdCat_19115.xml

<DS_Series xmlns="http://www.isotc211.org/2005/gmd" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:gsr="http://www.isotc211.org/2005/gsr" xmlns:gss="http://www.isotc211.org/2005/gss" xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd">
<composedOf>
    <DS_DataSet>
        <has>
            <MD_Metadata>
                <parentIdentifier>
                    <gco:CharacterString>NOAA ENC Product Catalog</gco:CharacterString>
                </parentIdentifier>
...
<EX_BoundingPolygon>
    <polygon>
        <gml:Polygon gml:id="US1AK90M_P1">
            <gml:exterior>
                <gml:LinearRing>
                    <gml:pos>67.61505 -178.99979</gml:pos>
                    <gml:pos>73.99999 -178.99979</gml:pos>
...
                    <gml:pos>64.99997 -178.99979</gml:pos>
                    <gml:pos>67.61505 -178.99979</gml:pos>
                </gml:LinearRing>

1 Ответ

11 голосов
/ 04 августа 2011

Я полагаю, что ваш DS_DataSet находится в пределах DS_Series (подразумевается пространство имен по умолчанию "http://www.isotc211.org/2005/gmd"), несущее пространство имен.

Попробуйте и отобразите это в свой словарь пространства имен (вы можете сначала протестировать черезотпечаток, чтобы увидеть, если он уже там, в противном случае добавьте его и обратитесь к пространству имен вашим новым ключом).

nsmap['some_ns'] = "http://www.isotc211.org/2005/gmd"
len (charts_tree.xpath('//*/some_ns:DS_DataSet',namespaces=nsmap))

Что становится:

nsmap['gmd'] = nsmap[None]
nsmap.pop(None)
len(charts_tree.xpath('//*/gmd:DS_DataSet',namespaces=nsmap))
...