如果存在默认命名空间,则 lxml xpath 不起作用



我的组织正在从python 2.7迁移到python 3.7。有一些 python 代码我没有编写,但必须迁移。代码使用 xml.xpath 来解析 xml。

鉴于 xml.xpath 在 python 3.7 中不可用。我正在尝试从lxml.etree移植代码以使用Xpath。目的是将代码更改量降至最低。

我已经粘贴了当前实现以及要将其移植到的代码。移植的代码不起作用,因为 XML 具有默认命名空间。

当前代码

>>> from xml import xpath
>>> from   xml.dom.minidom import parseString
>>> Test_XML = '<ibml:validateTradeStatusRequest xmlns="http://www.fpml.org/2005/FpML-4-2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:ibml="http://ibml.jpmorgan.com/2005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ibmlVersion="1-56" version="4-2" xsi:schemaLocation="http://ibml.jpmorgan.com/2005C:\IBTIBML\trunk\src\xsd\IBML.xsd"><header><sentBy>test_value</sentBy><sendTo>test_value</sendTo><creationTimestamp>2012-06-06T08:23:20.613</creationTimestamp></header><tradeReference></tradeReference></ibml:validateTradeStatusRequest>'
>>> doc = parseString( Test_XML )
>>> ctx = xpath.Context.Context( doc, processorNss = {'ibml' : 'http://ibml.jpmorgan.com/2005'} )
>>> expr = xpath.Compile( '/ibml:validateTradeStatusRequest/header/sentBy' )
>>> node = expr.evaluate(ctx)
>>> node[0].childNodes[0].data
u'test_value'
>>> 

尝试将其移植到 lxml.etree。但它不起作用,因为 XML 具有默认命名空间。

>>> from lxml import etree as ET
>>> element = ET.fromstring( Test_XML )
>>> element.xpath( '/ibml:validateTradeStatusRequest/header/sentBy', namespaces = {'ibml' : 'http://ibml.jpmorgan.com/2005'} )
[]

但是,如果我删除默认命名空间,则 xpath 评估工作正常。 但它不是理想的解决方案,因为 XML 创建超出了代码的范围。此外,无法更改 xpath 查询,因为这也超出了代码的范围。

>>> Test_XML_No_Default_NS = '<ibml:validateTradeStatusRequest xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:ibml="http://ibml.jpmorgan.com/2005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ibmlVersion="1-56" version="4-2" xsi:schemaLocation="http://ibml.jpmorgan.com/2005C:\IBTIBML\trunk\src\xsd\IBML.xsd"><header><sentBy>test_value</sentBy><sendTo>test_value</sendTo><creationTimestamp>2012-06-06T08:23:20.613</creationTimestamp></header><tradeReference></tradeReference></ibml:validateTradeStatusRequest>'
>>> ee = ET.fromstring( Test_XML_No_Default_NS )
>>> ee.xpath( '/ibml:validateTradeStatusRequest/header/sentBy', namespaces = {'ibml' : 'http://ibml.jpmorgan.com/2005'} )
[<Element sentBy at 0x1546b058>]
>>> node = _
>>> node[0].text
'test_value'

关于如何前进的任何建议?

我不确定这是否直接回答了您的问题,请尝试此操作,看看它是否有效(也许需要修改(

import lxml.etree
Test_XML = '<?xml version="1.0" encoding="UTF-8"?><ibml:validateTradeStatusRequest xmlns="http://www.fpml.org/2005/FpML-4-2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:ibml="http://ibml.jpmorgan.com/2005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ibmlVersion="1-56" version="4-2" xsi:schemaLocation="http://ibml.jpmorgan.com/2005C:\IBTIBML\trunk\src\xsd\IBML.xsd"><header><sentBy>test_value1</sentBy><sendTo>test_value2</sendTo><creationTimestamp>2012-06-06T08:23:20.613</creationTimestamp></header><tradeReference></tradeReference></ibml:validateTradeStatusRequest>'
xml = bytes(bytearray(Test_XML, encoding='utf-8')) 
ee = etree.XML(xml)
target = ee.xpath( '//ibml:validateTradeStatusRequest', namespaces = {'ibml' : 'http://ibml.jpmorgan.com/2005'} )
print(target[0].xpath('//text()')[0])

输出:

test_value1

最新更新