LXML:用名称空间替换字符串中的元素

时间:2017-11-09 17:45:24

标签: python xml lxml

如何使用相同的命名空间用字符串片段替换某个元素?

<!-- language: python -->
from lxml import etree

replacestring = '''<AP_PTO gml:id="DEAL123456789abc">
<new>This Element is new!</new>
</AP_PTO>'''


file = etree.parse("nasfile.xml")
root = file.getroot()
nsmap = root.nsmap.copy()
nsmap['adv'] = nsmap.pop(None)
nodes = root.xpath(".//adv:geaenderteObjekte/wfs:Transaction", namespaces=nsmap)
# Iterate object elements
for t in nodes[0]:
    for obj in t:
        oart = str(etree.QName(objekt.tag).localname)
        if oart == 'Filter':
            pass
        else:
            objid = (obj.xpath('@gml:id', namespaces=nsmap))[0][:16]
            if objid == 'DEAL123456789abc':
                t.replace(obj, etree.fromstring(replacestring))
                #nodes[0].remove(t)

我从输入文件中获取名称空间为nsmap:

{'adv': 'http://www.adv-online.de/namespaces/adv/gid/6.0',
 'asdkom': 'http://www.lverma.nrw.de/namespaces/kom-ok/1.1',
 'fc': 'http://www.adv-online.de/namespaces/adv/gid/fc/6.0',
 'gco': 'http://www.isotc211.org/2005/gco',
 'gmd': 'http://www.isotc211.org/2005/gmd',
 'gml': 'http://www.opengis.net/gml/3.2',
 'gsr': 'http://www.isotc211.org/2005/gsr',
 'gss': 'http://www.isotc211.org/2005/gss',
 'gts': 'http://www.isotc211.org/2005/gts',
 'ogc': 'http://www.adv-online.de/namespaces/adv/gid/ogc',
 'wfs': 'http://www.adv-online.de/namespaces/adv/gid/wfs',
 'wfsext': 'http://www.adv-online.de/namespaces/adv/gid/wfsext',
 'xlink': 'http://www.w3.org/1999/xlink',
 'xs': 'http://www.w3.org/2001/XMLSchema',
 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}

如果我从replacestring中删除gml:Prefix,则循环按预期工作。该字符串用给定的ID替换前一个元素。但是我用前缀得到了: XMLSyntaxError:未定义AP_PTO上id的名称空间前缀gml,第2行,第34列

如何告诉lxml使用源文件中nsmap中定义的命名空间?

1 个答案:

答案 0 :(得分:1)

任何使用命名空间的XML都必须声明这些命名空间,它总是需要自包含。

所以这个:

replacestring = '''<AP_PTO gml:id="DEAL123456789abc">
<new>This Element is new!</new>
</AP_PTO>'''

需要像这样:

replacestring = '''<AP_PTO gml:id="DEAL123456789abc" xmlns:gml="http://www.opengis.net/gml/3.2">
<new>This Element is new!</new>
</AP_PTO>'''

nsmap的目的是让Python了解XML使用的命名空间,而不是相反。

事实上,这就是它被命名为“map”的原因,它允许您选择要在XPath中使用的前缀。它将名称空间URI映射到短句柄。这样:

obj.xpath('@foobar:id', namespaces=nsmap)
如果您的nsmap正确定义foobar

将正常工作:

{'foobar': 'http://www.opengis.net/gml/3.2'}

在XML中使用什么前缀并不重要。前缀需要分别解析为正确的URI,并且URI需要相等。前缀本身不必相等。