【问题标题】:Python Lxml (objectify): Checking whether a tag existsPython Lxml(objectify):检查标签是否存在
【发布时间】:2011-07-20 03:21:35
【问题描述】:

我需要检查xml文件中是否存在某个标签。

比如我想看看这个sn-p中是否存在这个标签:

 <main>
       <elem1/>
       <elem2>Hi</elem2>
       <elem3/>
       ...
 </main>

目前,我正在使用带有错误检查功能的丑陋 hack,如下所示:

try:
   if root.elem1.tag:
      foo = elem1
except AttributeError:
   foo = "error finding elem1"

如果找不到节点(即“无法找到-tagname-”),我还想自定义字符串。

我必须检查一长串变量,我不想重复代码 100 次。

有什么建议吗?

编辑:

这是实际 xml 文件的片段:

<main>
 <asset name="Virtual Dvaered Unpresence">
  <virtual/>
  <presence>
   <faction>Dvaered</faction>
   <value>-1000.000000</value>
   <range>0</range>
  </presence>
 </asset>
 <asset name="Virtual Empire Small">
  <virtual/>
  <presence>
   <faction>Empire</faction>
   <value>100.000000</value>
   <range>2</range>
  </presence>
 </asset>
</main>

我想检查标签是否存在,如果存在,获取内容。

编辑编辑: 好的,我将结合两个答案,但我只能投票给一个。对不起。

编辑 3:此处有关 XPath 的相关问题:Python lxml (objectify): Xpath troubles

【问题讨论】:

    标签: python xml lxml objectify


    【解决方案1】:

    hasattr() 适用于此:

    if hasattr(root, 'elem1'):
        foo = root.elem1
    

    【讨论】:

    • 这是我喜欢的答案。它仍然很丑,但这是 Python 的错,而不是海报的错。我只是想检查孩子的存在,而不是启动一个完整的 xpath 处理器。
    • 请注意,内部 hasattr 通过调用 getattr 并捕获异常来工作,所以它的内部和外部一样丑陋(至少这是我上次检查的时候):)
    【解决方案2】:

    编辑:更新了示例文件的答案。

    我假设您想在每个资产中搜索某些标签。如果是这样,以下对我有用:

    import lxml.objectify
    
    # Parse the file.
    tree = lxml.objectify.parse('sample.xml')
    root = tree.getroot()
    
    # Which elements to find.
    to_find = set(['presence/faction', 'presence/value', 'fake'])
    
    # Go through each asset in the document.
    for asset in root.findall('asset'):
        # Check for each element. 
        for name in to_find:
            node = asset.find(name)
            if node is not None:
                print 'Found %s, its value is %s' % (name, node)
            else:
                print 'Unable to find %s' % name
    

    输出是:

    Found presence/value, its value is -1000.0
    Found presence/faction, its value is Dvaered
    Unable to find fake
    Found presence/value, its value is 100.0
    Found presence/faction, its value is Empire
    Unable to find fake
    

    【讨论】:

    • 这看起来会很好用。有机会我会试试的。澄清一下,您是否使用带有列表作为参数的 set()?
    • 是的。构造函数接受一个迭代来给出集合中的初始条目。详情请见the docs。
    • 好的,一个问题。我怎样才能使这个赋值给特定的变量(即 var_fac = present/faction,var_value = presence/value?
    • 我会使用字典。 if node is not None: values[name] = node等
    • 哦,我明白了,将值存储在字典中。我喜欢这个主意。
    【解决方案3】:

    假设你想获取elem2的值,你可以使用xpath找到它。

    tree = etree.parse(StringIO(htmlString), etree.HTMLParser()).getroot()
    youWantValue = tree.xpath('/main/elem2')[0].text
    

    【讨论】:

    • 如果节点不存在怎么办?它会给出错误,还是只是一个空白值?
    • @Biosci3c 该特定示例给出了错误,因为[0] 试图取消引用xpath 调用返回的第一个值。另一方面,如果您在取消引用之前检查了列表是否为空,那么您将获得一个没有错误的测试。顺便说一句,在进行了更正后,我发现这是给出的最佳实践答案。
    • 好的,我喜欢 XPATH 的建议,所以我也会使用它。顺便说一句,我认为您在顶行末尾缺少一个右括号。
    • 啊,所以我可以检查列表的长度是否为 0。好主意。
    • 好的,我尝试了您的方法的一个版本,但列表索引超出范围。我将在上面发布我的更新代码。
    【解决方案4】:

    如果您的文档相对较短,您可以遍历 &lt;main&gt; 的所有子代,以查找与您的变量名称集匹配的标签:

    tree = lxml.etree.fromstring(DATA)
    NAMES = set(['elem1', 'elem3'])
    for node in tree.iterchildren():
        if node.tag in NAMES:
            print 'found', node.tag
    

    或者您可以一次搜索每个变量名称:

    for tag in ('elem1', 'elem3'):
        if tree.find(tag) is not None:
            print 'found', tag
    

    【讨论】:

    • 我正在使用的文档很长。我会在问题中删减它。
    • 另外,第一行是否确定了搜索范围?
    猜你喜欢
    • 1970-01-01
    • 2018-06-08
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 2023-04-02
    相关资源
    最近更新 更多