如何解析xml以获得属性具有特定值的特定节点

2024-09-30 22:23:35 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面使用perl或python的xml中(这是最快的),我想要一种方法来获取attribute1设置为“characters”、attribute2没有设置为“chr”或attribute2本身没有的所有节点/节点名称。 请记住,我的xml可以有500个节点,所以请建议一种更快的方法来获取所有节点

<NODE attribute1="characters" attribute2="chr" name="node1"> <content> value1 </content> </NODE> <NODE attribute1="camera" name="node2"> <content> value2 </content> </NODE> <NODE attribute1="camera" attribute2="car" name="node3"> <content> value2 </content> </NODE>

Tags: 方法name名称node节点xmlcontent建议
3条回答

您要查找的是xpath表达式:

//NODE[@attribute1="characters" and ( not(@attribute2) or @attribute2="chr")]

使用xmllint进行快速测试:

kent$  cat f.xml
<root>
<NODE attribute1="characters" attribute2="chr" name="node1">
  <content>
    value1
  </content>
</NODE>

<NODE attribute1="camera"  name="node2">
  <content>
    value2
  </content>
</NODE>

<NODE attribute1="camera" attribute2="car" name="node3">
  <content>
    value2
  </content>
</NODE>
</root>

kent$  xmllint  xpath '//NODE[@attribute1="characters" and ( not(@attribute2) or @attribute2="chr")]' f.xml
<NODE attribute1="characters" attribute2="chr" name="node1">
  <content>
    value1
  </content>
</NODE>

更新

如果只想提取属性name的值,可以使用以下xpath:

//节点[@attribute1=“characters”和(不是(@attribute2)或@attribute2=“chr”)]/@name

或者 字符串(//节点[@attribute1=“characters”和(不是(@attribute2)或@attribute2=“chr”)]/@name)

仍使用xmllint进行测试:

kent$  xmllint  xpath '//NODE[@attribute1="characters" and ( not(@attribute2) or @attribute2="chr")]/@name' f.xml                                                          
 name="node1"

kent$  xmllint  xpath 'string(//NODE[@attribute1="characters" and ( not(@attribute2) or @attribute2="chr")]/@name)' f.xml
node1 

在您将其标记为perl/python时,我将提供一种perlish方法。你知道吗

Perl有一个很好的库^{},我非常喜欢它来解析XML。你知道吗

#!/usr/bin/perl

use strict;
use warnings;
use XML::Twig;

my $parser = XML::Twig->new();

#would probably use parsefile instead.
#e.g.:
# my $parser = XML::Twig -> new -> parsefile ( 'your_file.xml' );
{
    local $/;
    $parser->parse(<DATA>);
}


#iterate all the elements in the file. 
foreach my $element ( $parser->root()->children() ) {

    #test your conditions
    if ($element->att('attribute1') eq 'characters'
        and ( not defined $element->att('attribute2')
                       or $element->att('attribute2') eq 'chr' )
        )
    {
        #extract name if condition matches
        print $element ->att('name'), "\n";
    }
}


__DATA__
<DATA>
  <NODE attribute1="characters" attribute2="chr" name="node1">
    <content>
      value1
    </content>
  </NODE>

  <NODE attribute1="camera"  name="node2">
    <content>
      value2
    </content>  
  </NODE>

  <NODE attribute1="camera" attribute2="car" name="node3">
    <content>
      value2
    </content>
  </NODE>
</DATA>

使用lxml模块。你知道吗

content = """
<body>
<NODE attribute1="characters" attribute2="chr" name="node1">
  <content>
    value1
  </content>
</NODE>

<NODE attribute1="camera"  name="node2">
  <content>
    value2
  </content>
</NODE>

<NODE attribute1="camera" attribute2="car" name="node3">
  <content>
    value2
  </content>
</NODE>

<NODE attribute1="characters" attribute2="car" name="node3">
  <content>
    value2
  </content>
</NODE>

<NODE attribute1="characters" name="node3">
  <content>
    value2
  </content>
</NODE>

</body>
"""

from lxml import etree
root = etree.fromstring(content)
l = root.xpath('//*[@attribute1="characters" and ( not(@attribute2) or @attribute2!="chr") ]')
for i in l:
    print i.tag, i.attrib

输出:

$ python test.py 
NODE {'attribute2': 'car', 'attribute1': 'characters', 'name': 'node3'}
NODE {'attribute1': 'characters', 'name': 'node3'}

相关问题 更多 >