Python: 我如何使用 lxml objectify 的 iterchildren 获取不同命名空间中兄弟姐妹的详细信息
Python: How can I use lxml objectify's iterchildren to get details of siblings which are in a different namespace
这是我的 xml 文件。
get_subscribers_result.xml
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns3:GetSubscriberResponse xmlns:ns3="http://example.com/123/ss/subscribermgmt/v1_0" xmlns:ns2="http://example.com/123/ss/base/v1_0" xmlns:ns4="http://example.com/123/ss/xyz/v1_0" >
<ns3:subscriber>
<ns2:created>2015-10-20T16:02:58.831Z</ns2:created>
<ns2:createdBy>admin</ns2:createdBy>
<ns2:lastModified>2015-10-20T16:02:58.824Z</ns2:lastModified>
<ns2:lastModifiedBy>super</ns2:lastModifiedBy>
<ns2:subscriberDetail>
<ns2:key>address</ns2:key>
<ns2:value>1st vivekanandar street</ns2:value>
</ns2:subscriberDetail>
<ns2:subscriberDetail>
<ns2:key>state</ns2:key>
<ns2:value>Abu Dhabi</ns2:value>
</ns2:subscriberDetail>
</ns3:subscriber>
</ns3:GetSubscriberResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
现在,我看到了 http://davekuhlman.org/Objectify_files/weather_test.py 中使用 iterchildren 的示例。
如果没有命名空间,该代码可以工作。
如果我的 xml.
中没有名称空间,下面的代码将适用于我的 xml
obj2 = lxml.objectify.parse("get_subscribers_result.xml")
root = obj2.getroot()
tag = '{http://example.com/123/ss/base/v1_0}subscriberDetail'
for subscriberDetail in enumerate(root.subscriber.iterchildren(tag=tag)):
print subscriberDetail.key
print subscriberDetail.value
print "*********************************"
如果我 运行 这个,我得到
AttributeError: no such child: {http://schemas.xmlsoap.org/soap/envelope/}subscriber
那是因为订阅者不属于默认命名空间,这是正确的!
我试过了
for subscriberDetail in enumerate(root.{http://example.com/123/ss/subscribermgmt/v1_0}subscriber.iterchildren(tag=tag)):
有什么想法可以在存在名称空间的情况下实现这一点吗?
您可以改用 "namespace aware" xpath
函数并明确指定命名空间:
from lxml import objectify
obj2 = lxml.objectify.parse('get_subscribers_result.xml')
root = obj2.getroot()
tag = '{http://example.com/123/ss/base/v1_0}subscriberDetail'
for subscriberDetail in (root.xpath('//ns2:subscriberDetail', namespaces={'ns2': 'http://example.com/123/ss/base/v1_0'})):
print subscriberDetail.key
print subscriberDetail.value
print "*********************************"
如果你想遍历所有的节点,包括它们的子节点,你可以这样做:
for details in root.xpath('//SOAP-ENV:Envelope/descendant-or-self::*', namespaces={'SOAP-ENV':'http://schemas.xmlsoap.org/soap/envelope/','ns2': 'http://example.com/123/ss/base/v1_0','ns3':"http://example.com/123/ss/subscribermgmt/v1_0"}):
for element in details:
cleaned_tag = element.tag.replace('{'+element.nsmap[element.prefix]+'}','')
if element.text:
print("%s --> %s" % (element.prefix+':'+cleaned_tag,element.text))
这是我的 xml 文件。
get_subscribers_result.xml
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns3:GetSubscriberResponse xmlns:ns3="http://example.com/123/ss/subscribermgmt/v1_0" xmlns:ns2="http://example.com/123/ss/base/v1_0" xmlns:ns4="http://example.com/123/ss/xyz/v1_0" >
<ns3:subscriber>
<ns2:created>2015-10-20T16:02:58.831Z</ns2:created>
<ns2:createdBy>admin</ns2:createdBy>
<ns2:lastModified>2015-10-20T16:02:58.824Z</ns2:lastModified>
<ns2:lastModifiedBy>super</ns2:lastModifiedBy>
<ns2:subscriberDetail>
<ns2:key>address</ns2:key>
<ns2:value>1st vivekanandar street</ns2:value>
</ns2:subscriberDetail>
<ns2:subscriberDetail>
<ns2:key>state</ns2:key>
<ns2:value>Abu Dhabi</ns2:value>
</ns2:subscriberDetail>
</ns3:subscriber>
</ns3:GetSubscriberResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
现在,我看到了 http://davekuhlman.org/Objectify_files/weather_test.py 中使用 iterchildren 的示例。
如果没有命名空间,该代码可以工作。 如果我的 xml.
中没有名称空间,下面的代码将适用于我的 xml obj2 = lxml.objectify.parse("get_subscribers_result.xml")
root = obj2.getroot()
tag = '{http://example.com/123/ss/base/v1_0}subscriberDetail'
for subscriberDetail in enumerate(root.subscriber.iterchildren(tag=tag)):
print subscriberDetail.key
print subscriberDetail.value
print "*********************************"
如果我 运行 这个,我得到
AttributeError: no such child: {http://schemas.xmlsoap.org/soap/envelope/}subscriber
那是因为订阅者不属于默认命名空间,这是正确的!
我试过了
for subscriberDetail in enumerate(root.{http://example.com/123/ss/subscribermgmt/v1_0}subscriber.iterchildren(tag=tag)):
有什么想法可以在存在名称空间的情况下实现这一点吗?
您可以改用 "namespace aware" xpath
函数并明确指定命名空间:
from lxml import objectify
obj2 = lxml.objectify.parse('get_subscribers_result.xml')
root = obj2.getroot()
tag = '{http://example.com/123/ss/base/v1_0}subscriberDetail'
for subscriberDetail in (root.xpath('//ns2:subscriberDetail', namespaces={'ns2': 'http://example.com/123/ss/base/v1_0'})):
print subscriberDetail.key
print subscriberDetail.value
print "*********************************"
如果你想遍历所有的节点,包括它们的子节点,你可以这样做:
for details in root.xpath('//SOAP-ENV:Envelope/descendant-or-self::*', namespaces={'SOAP-ENV':'http://schemas.xmlsoap.org/soap/envelope/','ns2': 'http://example.com/123/ss/base/v1_0','ns3':"http://example.com/123/ss/subscribermgmt/v1_0"}):
for element in details:
cleaned_tag = element.tag.replace('{'+element.nsmap[element.prefix]+'}','')
if element.text:
print("%s --> %s" % (element.prefix+':'+cleaned_tag,element.text))