2013-07-09 65 views
2

好吧我会第一个承认它是,只是不是我想要的路径,我不知道如何得到它。LXML Xpath似乎没有返回完整路径

我在Eclipse中使用Python 3.3与Pydev插件在Windows 7在工作和Ubuntu 13.04在家里。我是python新手,编程经验有限。

我试图编写一个脚本来接受XML Lloyds市场保险消息,找到所有标签并将它们转储到.csv中,我们可以轻松更新它们,然后重新导入它们以创建更新的xml。

我已经设法做到了这一切,除了当我得到所有的标签,它只给出标签名称,而不是它上面的标签。

<TechAccount Sender="broker" Receiver="insurer"> 
<UUId>2EF40080-F618-4FF7-833C-A34EA6A57B73</UUId> 
<BrokerReference>HOY123/456</BrokerReference> 
<ServiceProviderReference>2012080921401A1</ServiceProviderReference> 
<CreationDate>2012-08-10</CreationDate> 
<AccountTransactionType>premium</AccountTransactionType> 
<GroupReference>2012080921401A1</GroupReference> 
<ItemsInGroupTotal> 
<Count>1</Count> 
</ItemsInGroupTotal> 
<ServiceProviderGroupReference>8-2012-08-10</ServiceProviderGroupReference> 
<ServiceProviderGroupItemsTotal> 
<Count>13</Count> 
</ServiceProviderGroupItemsTotal> 

这是XML的一个片段。我想要的是找到所有的标签和他们的路径。例如,我想将其显示为ItemsInGroupTotal/Count,但只能将其作为Count计算。

这里是我的代码:

xml = etree.parse(fullpath) 
print(xml.xpath('.//*')) 
all_xpath = xml.xpath('.//*') 
every_tag = [] 
for i in all_xpath: 
    single_tag = '%s,%s' % (i.tag, i.text) 
    every_tag.append(single_tag) 
print(every_tag) 

这给:

'{http://www.ACORD.org/standards/Jv-Ins-Reinsurance/1}ServiceProviderGroupReference,8-2012-08-10', '{http://www.ACORD.org/standards/Jv-Ins-Reinsurance/1}ServiceProviderGroupItemsTotal,\n', '{http://www.ACORD.org/standards/Jv-Ins-Reinsurance/1}Count,13', 

正如你所看到的计数显示为{命名空间}计数,13而不是{命名空间} ItemsInGroupTotal /计数,13

任何人都可以指向我需要的东西吗?

谢谢(希望我的第一篇文章是OK)

亚当

编辑:

这是我的代码现在: 开放(FULLPATH, 'RB')作为xmlFilepath: XMLFILE = xmlFilepath.read()

fulltext = '%s' % xmlfile 
text = fulltext[2:] 
print(text) 


xml = etree.fromstring(fulltext) 
tree = etree.ElementTree(xml) 

every_tag = ['%s, %s' % (tree.getpath(e), e.text) for e in xml.iter()] 
print(every_tag) 

但这返回一个错误: ValueError异常:Unicode字符串与ENCOD不支持声明。请不要声明使用字节输入或XML片段。

我删除了前两个字符作为你是B”,并抱怨它没有用标签开始

更新:

我一直在玩这个周围,如果我删除了红双喜: xxx标签和命名空间的东西在顶部按预期工作。我需要保留xis标签并能够将它们识别为xis标签,因此不能只删除它们。

任何帮助我如何实现这一目标?

回答

2

ElementTree objects have a method getpath(element), which returns a structural, absolute XPath expression to find that element

iter()循环中调用每个元素getpath应该为你工作:

from pprint import pprint 
from lxml import etree 


text = """ 
<TechAccount Sender="broker" Receiver="insurer"> 
    <UUId>2EF40080-F618-4FF7-833C-A34EA6A57B73</UUId> 
    <BrokerReference>HOY123/456</BrokerReference> 
    <ServiceProviderReference>2012080921401A1</ServiceProviderReference> 
    <CreationDate>2012-08-10</CreationDate> 
    <AccountTransactionType>premium</AccountTransactionType> 
    <GroupReference>2012080921401A1</GroupReference> 
    <ItemsInGroupTotal> 
     <Count>1</Count> 
    </ItemsInGroupTotal> 
    <ServiceProviderGroupReference>8-2012-08-10</ServiceProviderGroupReference> 
    <ServiceProviderGroupItemsTotal> 
     <Count>13</Count> 
    </ServiceProviderGroupItemsTotal> 
</TechAccount> 
""" 

xml = etree.fromstring(text) 
tree = etree.ElementTree(xml) 

every_tag = ['%s, %s' % (tree.getpath(e), e.text) for e in xml.iter()] 
pprint(every_tag) 

打印:

['/TechAccount, \n', 
'/TechAccount/UUId, 2EF40080-F618-4FF7-833C-A34EA6A57B73', 
'/TechAccount/BrokerReference, HOY123/456', 
'/TechAccount/ServiceProviderReference, 2012080921401A1', 
'/TechAccount/CreationDate, 2012-08-10', 
'/TechAccount/AccountTransactionType, premium', 
'/TechAccount/GroupReference, 2012080921401A1', 
'/TechAccount/ItemsInGroupTotal, \n', 
'/TechAccount/ItemsInGroupTotal/Count, 1', 
'/TechAccount/ServiceProviderGroupReference, 8-2012-08-10', 
'/TechAccount/ServiceProviderGroupItemsTotal, \n', 
'/TechAccount/ServiceProviderGroupItemsTotal/Count, 13'] 

UPD: 如果你的XML数据文件test.xml中,该代码将如下所示:

from pprint import pprint 
from lxml import etree 

xml = etree.parse('test.xml').getroot() 
tree = etree.ElementTree(xml) 

every_tag = ['%s, %s' % (tree.getpath(e), e.text) for e in xml.iter()] 
pprint(every_tag) 

希望有所帮助。

+0

非常感谢这个,但我很难让它为我工作。我从文件中读取XML,而不是直接将其放入文本中,我试图将其转换为字符串似乎失败。关于实现这个的任何提示? – user2565150

+0

当然,用'etree.parse(file_name)'替换'etree.fromstring(text)'。 – alecxe

+0

对不起,应该说我尝试了,得到:TypeError:参数'元素'有不正确的类型(预期lxml.etree._Element,得到lxml.etree._ElementTree) – user2565150

1

getpath()确实会返回不适合人类消费的xpath。从这个xpath,你可以建立一个更有用的一个。比如用这种快速和肮脏的方法:

def human_xpath(element): 
    full_xpath = element.getroottree().getpath(element) 
    xpath = '' 
    human_xpath = '' 
    for i, node in enumerate(full_xpath.split('/')[1:]): 
     xpath += '/' + node 
     element = element.xpath(xpath)[0] 
     namespace, tag = element.tag[1:].split('}', 1) 
     if element.getparent() is not None: 
      nsmap = {'ns': namespace} 
      same_name = element.getparent().xpath('./ns:' + tag, 
                namespaces=nsmap) 
      if len(same_name) > 1: 
       tag += '[{}]'.format(same_name.index(element) + 1) 
     human_xpath += '/' + tag 
    return human_xpath 
相关问题