python - lxml - 使用 find 方法查找特定标签? (没有找到)

标签 python xml lxml

我有一个 xml 文件,需要更新某些特定标签的某些值。在 header 标签中,有一些带有命名空间的标签。对此类标签使用 find 是可行的,但如果我尝试搜索一些其他没有 namespace 的标签,它找不到它。

我尝试了相对、绝对路径,但没有找到。代码是这样的:

from lxml import etree

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

# get its namespace map, excluding default namespace
nsmap = {k:v for k,v in root.nsmap.iteritems() if k}

# Replace values in tags

identity = tree.find('.//env:identity', nsmap)
identity.text = 'Placeholder' # works fine

e01_0017 = tree.find('.//e01_0017') # does not find
e01_0017.text = 'Placeholder' # and then it throws this ofcourse: AttributeError: 'NoneType' object has no attribute 'text'

# Also tried like this, but still not working
e01_0017 = tree.find('Envelope/Body/IVOIC/UNB/cmp04/e01_0017')

我什至尝试查找例如 body 标记,但它也没有找到。

这是 xml 结构的样子:

    <?xml version="1.0" encoding="ISO-8859-1"?><Envelope xmlns="http://www.someurl.com/TTT"  xmlns:env="http://www.someurl.com/TTT_Envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.someurl.com/TTT TTT_INVOIC.xsd"><Header>
    <env:delivery>
        <env:to>
            <env:address>Test</env:address>
        </env:to>
        <env:from>
            <env:address>Test2</env:address>
        </env:from>
        <env:reliability>
            <env:sendReceiptTo/>
            <env:receiptRequiredBy/>
        </env:reliability>
    </env:delivery>
    <env:properties>
        <env:identity>some code</env:identity>
        <env:sentAt>2006-03-17T00:38:04+01:00</env:sentAt>
        <env:expiresAt/>
        <env:topic>http://www.someurl.com/TTT/</env:topic>
    </env:properties>
    <env:manifest>
        <env:reference uri="#INVOIC@D00A">
            <env:description>Doc Name Descr</env:description>
        </env:reference>
    </env:manifest>
    <env:process>
        <env:type></env:type>
        <env:instance/>
        <env:handle></env:handle>
    </env:process>
</Header>
    <Body>     
    <INVOIC>
                <UNB>
                    <cmp01>
                        <e01_0001>1</e01_0001>
                        <e02_0002>1</e02_0002>
                    </cmp01>
                    <cmp02>
                        <e01_0004>from</e01_0004>
                    </cmp02>
                    <cmp03>
                        <e01_0010>to</e01_0010>
                    </cmp03>
                    <cmp04>
                        <e01_0017>060334</e01_0017>
                        <e02_0019>1652</e02_0019>
                    </cmp04>
                    <e01_0020>1</e01_0020>
                    <cmp05>
                        <e01_0022>1</e01_0022>
                    </cmp05>
                </UNB>
    </INVOIC>
    </Body>
    </Envelope>

更新 header 或信封标签似乎有问题。例如,如果我使用没有 header 和信封信息的 xml,那么可以很好地找到标签。如果我包含信封属性和标题,它将停止查找标签。使用 header 信息更新了 xml 示例

最佳答案

问题是你的元素像 e01_0017也有一个命名空间,它从其父级命名空间继承其命名空间,在这种情况下,它一直回到 - <Envelope> 。您的元素的命名空间是 - "http://www.someurl.com/TTT" .

你有两个选择,

  1. 直接在 XPATH 中指定命名空间,示例 -

    e01_0017 = tree.find('.//{http://www.someurl.com/TTT}e01_0017')
    

    演示(用于您的 xml)-

    In [39]: e01_0017 = tree.find('.//{http://www.someurl.com/TTT}e01_0017')
    
    In [40]: e01_0017
    Out[40]: <Element {http://www.someurl.com/TTT}e01_0017 at 0x2fe78c8>
    
  2. 另一个选项是将其添加到 nsmap为该键设置一些默认值,然后在 xpath 中使用它。示例-

    nsmap = {(k or 'def'):v for k,v in root.nsmap.items()}
    e01_0017 = tree.find('.//def:e01_0017',nsmap)
    

关于python - lxml - 使用 find 方法查找特定标签? (没有找到),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33252221/

相关文章:

python - 使用 python 2.7.10 的 matplotlib.pyplot 和 wx 导入问题

python - 如何根据用户输入循环回到以前的意图?

javascript - NativeScript 中的 Accordion

python - 为什么我的 python 请求检索到不正确的 xml?

python - BeautifulSoup: 'lxml' 和 'html.parser' 以及 'html5lib' 解析器有什么区别?

python - numpy 数组的时髦行为

python - (Python MySQLdb) 尝试将 UTF-8 插入 MySQL 时

c# - XML 序列化错误 - 类型 'ItemsElementName' 的选择标识符 'ItemsChoiceType[]' 的值无效或缺失

java - 如何访问 SOAP 消息元素?

python - 如何使用本地DTD文件使用lxml解析XML文件?