【发布时间】:2020-01-03 15:40:17
【问题描述】:
我的组织正在从 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'
对我如何前进有什么建议吗?
【问题讨论】:
-
代码使用 xml.xpath 解析 xml。什么是 xml.xpath? “当前代码”中没有导入语句。
-
我发现 xml.xpath 是旧的且未维护的 PyXML 包 (sourceforge.net/projects/pyxml) 的一部分。
-
@mzjn 抱歉给您添麻烦了。编辑了问题并添加了导入语句。
-
无论如何,我看不到在不更改 XPath 查询字符串的情况下做你想做的事的方法。 lxml 还需要默认命名空间的前缀:
NSMAP = {'ibml':'http://ibml.jpmorgan.com/2005', 'd': 'http://www.fpml.org/2005/FpML-4-2'})。然后element.xpath('/ibml:validateTradeStatusRequest/d:header/d:sentBy', namespaces=NSMAP)就可以了。
标签: python xml lxml python-3.7