XML解析会忽略文本

时间:2019-01-15 10:34:25

标签: python xml python-3.x xml-parsing elementtree

我遇到以下问题,试图从python中的一堆xml文件中获取信息。我没有做任何特别的事情,例如:

import xml.etree.ElementTree as ET

root = ET.parse(r'C:\Documents\XMLfolder\file.xml').getroot()
info = root.find('foo').find('bar').find('info').text

这适用于我拥有的大多数信息-但xml的一部分采用以下格式:

<bar>
<info id="1"><label>1</label>SampleTextHere</info>
</bar>

上面的代码给出了None-我可以找到info元素和label元素。我只是找不到文字。如果我编辑文件以删除<label> 1 </label>,则上面的代码将返回我需要的文本。

是否存在一些我不知道的非常基本的东西,这些东西将允许我访问文本而无需修改所有xml文件来删除标签? (这是相关的)。

谢谢!

1 个答案:

答案 0 :(得分:1)

来自[Python 3]: xml.etree.ElementTree.Element.text重点是我的):

  

这些属性可用于保存与元素关联的其他数据。 它们的值通常是字符串,但可以是任何特定于应用程序的对象。如果该元素是从XML文件创建的,则 text 属性将保留元素的开始标记与其第一个子标记或结束标记之间的文本,或者None tail之间的文本。 属性保存元素的结束标签和下一个标签之间的文本,或者保存None

     

...

     

要收集元素的内部文本,请参见itertext() ,例如"".join(element.itertext())

我根据您的规范创建了3个文件:

  • file0.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1">SampleTextHere 0</info>
        </bar>
      </foo>
    </root>
    
  • file1.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1"><label>LabelText</label>SampleTextHere 1</info>
        </bar>
      </foo>
    </root>
    
  • file2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1"></info>
        </bar>
      </foo>
    </root>
    

和一些示例代码。

code.py

#!/usr/bin/env python3

import sys
import xml.etree.ElementTree as ET


def main():
    file_names = [
        "file0.xml",
        "file1.xml",
        "file2.xml",
    ]

    for file_name in file_names:
        root = ET.parse(file_name).getroot()
        info_node = root.find("foo").find("bar").find("info")
        text = info_node.text
        tail = info_node.tail
        iter_text = "".join(info_node.itertext())
        info_node_text = text or ""
        if not info_node_text:
            for info_node_text in info_node.itertext():
                pass
        print("\n{:s}\n      Text (for debugging purposes): [{:}]\n      Tail (for debugging purposes): [{:}]\n      Iter text (for debugging purposes): [{:s}]\n  Value: [{:s}]".format(
            file_name, text, tail, iter_text, info_node_text))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main() 

该算法非常简单:如果节点未设置 text 属性,则迭代其itertext()并选择最后一个值作为 label (或任何其他)子节点位于文本之前。

输出

(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054197111>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32


file0.xml
      Text (for debugging purposes): [SampleTextHere 0]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): [SampleTextHere 0]
  Value: [SampleTextHere 0]

file1.xml
      Text (for debugging purposes): [None]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): [LabelTextSampleTextHere 1]
  Value: [SampleTextHere 1]

file2.xml
      Text (for debugging purposes): [None]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): []
  Value: []