【问题标题】:Python: Parsing an XML file with several attributes in one nodePython:在一个节点中解析具有多个属性的 XML 文件
【发布时间】:2016-11-03 12:34:41
【问题描述】:

我还是编程新手,但我了解一些 Python,并且对 XPath 和 XML 很熟悉。目前我正在处理一些看起来像这样的 XML 数据:

<foo>
  <bar>
      <unit>
          <structure>
              <token word="Rocky" att1="noun" att2="name">Rocky</token>
              <token word="the" att1="article" att2="">the</token>
              <token word="yellow" att1="adjective" att2="color">yellow</token>
              <token word="dog" att1="noun" att2="animal">dog</token>
          </structure>
      </unit>
  </bar>
</foo>

现在我需要做的是先找到一个属性值,让我们采取

<token word="dog" att1="noun"att2="animal"</token>

举个例子。因此,在文档中的所有结构中,我想首先找到所有具有 animal 作为 att2 值的节点,然后将该节点的所有兄弟节点放入一个列表中。因为每个节点都有几个属性,所以我试图将它们中的每一个都包含在一个不同的列表中,也就是说,从结构中具有 animal 的所有属性中创建一个列表其子项的 att2 值之一。例如:

 listWord = [Rocky, the, yellow, dog]
 listAtt1 = [noun, article, adjective, noun]
 listAtt2 = [name, ,color, animal]

目前我只是想知道这是否可能。到目前为止,我只是设法用属性结构撞到了墙上,更不用说空值了。

【问题讨论】:

  • 您的 XML 无效,它错过了一些关闭 > 标记
  • 您的 XML 结构已损坏,所有 &lt;token&gt; 标记都缺少结束 &gt;,可能是复制和粘贴错误。
  • THEN 将该节点的所有兄弟节点放入一个列表中。 => 你到底怎么称呼兄弟姐妹?
  • 示例listWord listAtt1listAtt2 是您要构建的列表吗?
  • 哎呀,是的,只是在构建结构时忘记了关闭。但他们就在那里。

标签: python xml xpath elementtree


【解决方案1】:

我不确定我是否理解您的问题,但以下是我理解的部分(使用 lxml 和 xpath):

from lxml import etree
tree = etree.fromstring("""<foo>
  <bar>
      <unit>
          <structure>
              <token word="Rocky" att1="noun" att2="name"></token>
              <token word="the" att1="article" att2=""></token>
              <token word="yellow" att1="adjective" att2="color"></token>
              <token word="dog" att1="noun" att2="animal"></token>
          </structure>
      </unit>
  </bar>
</foo>""")


// get a list of all possible words, att1, att2:
listWord = tree.xpath("//token/@word")
listAtt1 = tree.xpath("//token/@att1")
listAtt2 = tree.xpath("//token/@att2")

// get all the tokens with att2="animal"
for token in tree.xpath('//token[@att2="animal"]'):
    do_your_own_stuff()

【讨论】:

    【解决方案2】:

    包含结束标记,并假设您的文本包含在 test.xml 中,以下内容:

    import xml.etree.ElementTree
    
    e = xml.etree.ElementTree.parse('test.xml').getroot()
    
    listWord = []
    listAtt1 = []
    listAtt2 = []
    
    for child in e.iter('token'):
        listWord.append(child.attrib['word'])
        listAtt1.append(child.attrib['att1'])
        listAtt2.append(child.attrib['att2'])
    
    print listWord
    print listAtt1
    print listAtt2
    

    将返回:

    ['Rocky', 'the', 'yellow', 'dog']
    ['noun', 'article', 'adjective', 'noun']
    ['name', '', 'color', 'animal']
    

    e.iter() 允许您迭代 e 作为根及其下方的元素 - 我们指定 token 的标签只返回 token 元素。 child.attrib 返回一个属性字典,我们将其附加到列表中。

    编辑:对于您问题的第二点,我认为以下内容(尽管可能不是最佳实践)可以满足您的需求:

    import xml.etree.ElementTree
    
    e = xml.etree.ElementTree.parse('test.xml').getroot()
    
    listWord = []
    listAtt1 = []
    listAtt2 = []
    animal_structs =[]
    
    for structure in e.iter('structure'):
        for child in structure.iter('token'):
            if 'att2' in child.keys():
                if child.attrib['att2'] == 'animal':
                    animal_structs.append(structure)
                    break
    
    for structure in animal_structs:
        for child in structure.iter('token'):
            listWord.append(child.attrib['word'])
            listAtt1.append(child.attrib['att1'])
            listAtt2.append(child.attrib['att2'])
    
    print listWord
    print listAtt1
    print listAtt2
    

    我们首先创建一个包含structure 子元素的所有structure 元素的列表,然后返回每个结构的所有then 属性。

    【讨论】:

    • 这看起来很有希望,但我得到的仍然是:if child.attrib['att2'] == 'animal': KeyError: 'att2'
    • 我们需要检查 token 是否有这个键 - 我已经编辑了这个。
    • 你是对的。当我用一个简短的 XML 提取测试它时,这可以完美地工作,但用原始 XML 文件却没有那么多。那肯定是有什么问题。
    • 我不断收到相同的密钥错误。可能还有一些我忘记的上层结构或其他一些原因它无法识别属性 att2。
    • 如果您添加了if 'att2' in child.keys() 行,您不应该得到同样的错误,所以我在这里有点困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多