2

好的,我会第一个承认它是,只是不是我想要的路径,我不知道如何得到它。

我在工作中的 Windows 7 和家里的 ubuntu 13.04 中都在 Eclipse 中使用 Python 3.3 和 Pydev 插件。我是 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',

如您所见,Count 显示为 {namespace}Count, 13 而不是 {namespace}ItemsInGroupTotal/Count, 13

谁能指出我需要什么?

谢谢(希望我的第一篇文章还可以)

亚当

编辑:

这是我现在的代码: with open(fullpath, 'rb') as 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 字符串。请使用未声明的字节输入或 XML 片段。

我删除了前两个字符,因为你是 b' 并且它抱怨它没有以标签开头

更新:

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

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

4

2 回答 2

2

ElementTree 对象有一个方法 getpath(element),它返回一个结构化的、绝对的 XPath 表达式来查找该元素

调用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)

希望有帮助。

于 2013-07-09T22:04:48.453 回答
2

getpath()确实返回了一个不适合人类消费的 xpath。不过,您可以从这个 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
于 2013-07-30T15:42:51.103 回答