代码之家  ›  专栏  ›  技术社区  ›  geotheory

使用lxml和elementtree解析XML

  •  0
  • geotheory  · 技术社区  · 11 年前

    我正在尝试解析XML文档以返回 <input> 包含 ref 属性玩具示例有效,但文档本身返回一个空数组,当它应该显示匹配项时。

    玩具示例

    import elementtree.ElementTree
    from lxml import etree
    tree = etree.XML('<body><input ref="blabla"><label>Cats</label></input><input ref="blabla"><label>Dogs</label></input><input ref="blabla"><label>Birds</label></input></body>')
    # I can return the relevant input nodes with:
    print len(tree.findall(".//input[@ref]"))
    2
    

    但由于某些原因,使用以下(缩减)文件失败:

    示例.xml

    <?xml version="1.0"?>
    <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <h:head>
        <h:title>A title</h:title>
      </h:head>
      <h:body>
        <group ref="blabla">
          <label>Group 1</label>
          <input ref="blabla">
            <label>Field 1</label>
          </input>
        </group>
      </h:body>
    </h:html>
    

    剧本

    import elementtree.ElementTree
    from lxml import etree
    with open ("example.xml", "r") as myfile:
      xml = myfile.read()
    tree = etree.XML(xml)
    print len(tree.findall(".//input[@ref]"))
    0
    

    知道为什么会失败吗?如何解决?我认为这可能与XML标头有关。非常感谢您的帮助。

    2 回复  |  直到 11 年前
        1
  •  2
  •   sideshowbarker    11 年前

    我认为问题是整个文档中的元素都在特定的名称空间中,因此没有名称空间的 .findall(".//input[@ref]")) 表达式与 input 元素,它实际上是一个命名空间 输入 元素,在 http://www.w3.org/2002/xforms 命名空间。

    所以不妨试试这个:

    .findall(".//{http://www.w3.org/2002/xforms}input[@ref]")
    

    已更新 在我最初的答案之后,使用xforms名称空间而不是xhtml名称空间(如另一个答案中所述)。

        2
  •  2
  •   Anand S Kumar    11 年前

    从xml中可以看出,无前缀元素的xml命名空间是- "http://www.w3.org/2002/xforms" ,这是因为它被定义为 xmlns 父元素中没有任何前缀 h:html ,仅元素前缀 h: 将命名空间设置为 "http://www.w3.org/1999/xhtml" .

    因此,您也需要在查询中使用该名称空间。示例-

    root.findall(".//{http://www.w3.org/2002/xforms}input[@ref]")
    

    示例/演示-

    >>> s = """<?xml version="1.0"?>
    ... <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    ...   <h:head>
    ...     <h:title>A title</h:title>
    ...   </h:head>
    ...   <h:body>
    ...     <group ref="blabla">
    ...       <label>Group 1</label>
    ...       <input ref="blabla">
    ...         <label>Field 1</label>
    ...       </input>
    ...     </group>
    ...   </h:body>
    ... </h:html>"""
    >>> import xml.etree.ElementTree as ET
    >>> root = ET.fromstring(s)
    >>> root.findall(".//{http://www.w3.org/1999/xhtml}input[@ref]")
    >>> root.findall(".//{http://www.w3.org/2002/xforms}input[@ref]")
    [<Element '{http://www.w3.org/2002/xforms}input' at 0x02288EA0>]