【问题标题】:Select a node with a particular element value in XML using python 2.7 and XML element tree使用 python 2.7 和 XML 元素树在 XML 中选择具有特定元素值的节点
【发布时间】:2015-04-08 10:22:17
【问题描述】:

我整个上午都在为此苦苦挣扎,但我无法让它发挥作用。

我有一个这样的 XML(精简匿名版本):

<?xml version="1.0" encoding="UTF-8"?>
<Root>
  <First_Level_Node>
    <Element_Name>
      <attribute1>1</attribute1>
      <attribute2>2</attribute2>
      <attribute3>3</attribute3>
      <attribute4>4</attribute4>
      <attribute5>5</attribute5>
      <attribute6>6</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>42</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random value</attribute5>
      <attribute6>18th Jun 2014  07:09:18 GMT</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>42</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>23rd Jul 2014  02:47:10 GMT</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>42</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>08th Nov 2014  23:53:31 GMT</attribute6>
    </Element_Name>
  </First_Level_Node>
</Root>

现在我已经从所有元素中获取了一些值并使用它们。

但现在我只想选择具有特定属性值对的元素。

例如,在我粘贴的 xml 中,我只需要使用 attribute4 = 42

获取元素

我目前的代码如下:

tree=ET.parse('xmlname.xml')
root=tree.getroot()
for slot in input_data:
        for child in root[0]:
            for ch in child.findall('First Level Node/*/[@attribute4="' + str(sys.argv[1]) + '"]'):
                print ch
                if ch.tag == slot:
                    if ch.text == 'UNCOMPUTED' or ch.text == None:
                        slot_text.append("Undefined")
                    else:
                        slot_text.append(ch.text)
        data[slot]=Counter(slot_text).most_common()

但我在 ch 中没有得到任何值。我已经尝试了相同的多种变体以及我所知道的所有 Xpath,但仍然没有结果。

任何帮助将不胜感激。

注意:Element_Name 是动态的,可以更改。

编辑:试过了,但输出的信息有误。

for slot in input_data:
        for child in root[0]:
            for ch in child:
                if ch.text == '42' and ch.tag == "attribute4":
                    flag=1
                if ch.tag == slot and flag == 1:
                    flag=0
                    if ch.text == 'UNCOMPUTED' or ch.text == None:
                        slot_text.append("Undefined")
                    else:
                        slot_text.append(ch.text)
        data[slot]=Counter(slot_text).most_common()

【问题讨论】:

    标签: python xml xpath elementtree


    【解决方案1】:

    &lt;attribute4&gt; 是一个 XML 元素,而不是 XML 属性。所以,我首先要尝试的是以下 XPath:

    .....
    xpath = 'First Level Node/*[attribute4="' + str(sys.argv[1]) + '"]'
    for ch in child.findall(xpath):
    ......
    

    *) 旁注:“一级节点”不是有效的 XML 元素示例,因为它包含空格

    更新:

    在您的 XML 示例上下文中,child 变量已经指向 &lt;First_Level_Node&gt;,它是 &lt;Root&gt; 的子代:

    for child in root[0]:
    

    因此,您需要从 XPath 中删除 First_Level_Node

    .....
    xpath = '*[attribute4="' + str(sys.argv[1]) + '"]'
    for ch in child.findall(xpath):
    ......
    

    【讨论】:

    • 我已经试过了,没有结果。(而且“一级节点”实际上不叫那个,实际数据没有空格。)
    • @KaranpreetSingh 好的,最好将您的 XML 精简到更简单,但要保持正确并仍然保留问题,以便我们可以分析是什么让它表现得这样:Short, Self Contained, Correct (Compilable), Example。否则,只能胡乱猜测了……
    • 老兄,你有下面的答案,只需将这个不可读的行替换为 child.findall('First Level Node/*/[@attribute4="' + str(sys.argv[1]) + '"]'): 如果 ch.tag == "attribute4" 和 ch.text == "42" 的话,你将拥有所有的元素只有 attribute4 = 42
    • 我在在线 xpath 测试器中尝试了 xpath 查询,它可以工作,但我似乎无法在 findall() 调用中让它工作。
    • @KaranpreetSingh 如果您尝试使用有问题的 XML 版本会发生什么?如果问题仍然存在,那么我们有机会分析并提出解决方案,否则请先编辑您的示例 XML...
    【解决方案2】:

    试试这个:

    tree=ET.parse('xmlname.xml')
    root=tree.getroot()
    
    for first_level_node in root:
        for element_name in first_level_node:
            for attribute in element_name:
                if attribute.tag == "attribute4" and attribute.text == "42":
                # do something
    

    【讨论】:

    • 您能否解释一下为什么原始代码不起作用,而您的代码却起作用?纯代码答案没有多大帮助。
    • 我只是在树中循环,假设树将始终具有相同数量的级别。我不能告诉你为什么他的代码不工作,因为他的代码不完整/有错误。首先 input_data 没有定义,孩子也是嵌套的,所以 root[0] 你跳过了一个级别,使它不可读,如果他只想读取文本值等于 42 的所有元素,我认为 .text 会是findall 模式更容易
    • 我也错过了检查attribute.tag是否等于attribute4,将编辑我的答案
    • @lapinkoira 我之前在代码中定义了 input_data ,它与 xml 无关,因此我没有进一步扩展。
    • @lapinkoira 另外,我想读取该节点中的其他元素,而不是我正在比较的相等条件。例如,如果attribute4 == 42,那么我想获取attribute1 到6 的值,当然对于那个element_name 是4。另外,您能否澄清一下您是否打算使用“if ch.tag == slot: #code part of if”代替“#do something”或 for 循环遍历属性?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 2011-07-06
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    相关资源
    最近更新 更多