【问题标题】:lxml xpath in python, how to handle missing tags?python中的lxml xpath,如何处理丢失的标签?
【发布时间】:2012-06-13 19:50:07
【问题描述】:

假设我想用 lxml xpath 表达式解析下面的 xml

<pack xmlns="http://ns.qubic.tv/2010/item">
    <packitem>
        <duration>520</duration>
        <max_count>14</max_count>
    </packitem>
    <packitem>
        <duration>12</duration>
    </packitem>
</pack>

这是 http://python-thoughts.blogspot.fr/2012/01/default-value-for-text-function-using.html 的变体

我怎样才能实现对不同元素的解析,一旦被压缩(在 zip 或 izip python 函数意义上)就会给我

[(520,14),(12,无)]

?

第二个包装中缺少的max_count 标签让我无法得到我想要的东西。

【问题讨论】:

    标签: python xml lxml


    【解决方案1】:
    def lxml_empty_str(context, nodes):
        for node in nodes:
            node.text = node.text or ""
        return nodes
    
    ns = etree.FunctionNamespace('http://ns.qubic.tv/lxmlfunctions')
    ns['lxml_empty_str'] = lxml_empty_str
    
    namespaces = {'i':"http://ns.qubic.tv/2010/item",
              'f': "http://ns.qubic.tv/lxmlfunctions"}
    packitems_duration = root.xpath('f:lxml_empty_str('//b:pack/i:packitem/i:duration)/text()',
    namespaces={'b':billing_ns, 'f' : 'http://ns.qubic.tv/lxmlfunctions'})
    packitems_max_count = root.xpath('f:lxml_empty_str('//b:pack/i:packitem/i:max_count)    /text()',
    namespaces={'b':billing_ns, 'f' : 'http://ns.qubic.tv/lxmlfunctions'})
    packitems = zip(packitems_duration, packitems_max_count)
    
    >>> packitems
    [('520','14'), ('','23')]
    

    http://python-thoughts.blogspot.fr/2012/01/default-value-for-text-function-using.html

    【讨论】:

      【解决方案2】:

      您可以使用xpath 找到packitems,然后再次调用xpath(或findtext,如下所示)找到durationmax_counts。不得不多次致电xpath 可能不会很快,但它确实有效。

      import lxml.etree as ET
      
      content = '''<pack xmlns="http://ns.qubic.tv/2010/item">
          <packitem>
              <duration>520</duration>
              <max_count>14</max_count>
          </packitem>
          <packitem>
              <duration>12</duration>
          </packitem>
      </pack>
      '''
      
      def make_int(text):
          try:
              return int(text)
          except TypeError:
              return None
      
      namespaces = {'ns' : 'http://ns.qubic.tv/2010/item'}
      doc = ET.fromstring(content)
      result = [tuple([make_int(elt.findtext(path, namespaces = namespaces))
                                 for path in ('ns:duration', 'ns:max_count')])
                for elt in doc.xpath('//ns:packitem', namespaces = namespaces) ]
      print(result)
      # [(520, 14), (12, None)]
      

      另一种方法是使用 SAX 解析器。这可能会快一点,但它需要更多的代码,如果 XML 不是很大,速度差异可能并不重要。

      【讨论】:

      • 非常感谢您花时间研究我的用例。我已经有一个类似于你的解决方案,如果可能的话,我希望有一个完整的 xpath 方法。最好的问候
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      相关资源
      最近更新 更多