代码之家  ›  专栏  ›  技术社区  ›  Cyprian Gepfert

用python中的任意前缀按标记分析xml节点子列表

  •  1
  • Cyprian Gepfert  · 技术社区  · 10 年前

    我想得到一份与前缀无关的项目列表。 我的目标是创建一个具有一个参数(标记名)并返回元素列表的方法(如果存在类似的方法,请注意我)。

    例如,在参数“item”的情况下 <media:item> , <abc:item> 应该是此函数结果的一部分。

    使用lxml会很好,但它可以是任何基于python DOM的解析器。

    不幸的是,我不能假设xml有xmlns,这就是为什么我需要解析任何前缀。

    1 回复  |  直到 10 年前
        1
  •  1
  •   Community Mohan Dere    9 年前

    lxml 是一个不错的选择,主要是因为它通过 xpath() 方法以及许多其他有用的实用程序。在XPath中,可以使用 local-name() 如评论中所述。

    lxml文件 还可以通过设置参数来处理未定义的前缀 recover=True ,但现在,问题来了; local-name() 对于具有未定义前缀的元素,仍然返回带前缀的“标记名”。有一种简单的方法来匹配这类元素,即找到本地名称的元素 包含 :tagname -或者更准确地说,找到本地名称的元素 ends with :标记名 而不是 包含 -.

    以下是演示的工作示例。演示使用了两个与逻辑运算符组合的表达式 or ; 一个用于处理具有未定义前缀的元素,另一个用于没有前缀或具有正确定义的前缀的元素:

    from lxml import etree
    
    xml = """<root foo="bar">
        <media:item>a</media:item>
        <abc:item>b</abc:item>
        <foo:item>c</foo:item>
        <item>d</item>
    </root>"""
    parser = etree.XMLParser(recover=True)
    tree = etree.fromstring(xml, parser=parser)
    tagname = "item"
    #expression to match element undefined prefix
    predicate1 = "contains(local-name(),':{0}')".format(tagname)
    #expression to match element with properly defined prefix or with no prefix
    predicate2 = "local-name()='{0}'".format(tagname)
    elements = tree.xpath("//*[{0} or {1}]".format(predicate1, predicate2))
    for e in elements:
        print(etree.tostring(e))
    

    输出:

    <media:item>a</media:item>
    
    <abc:item>b</abc:item>
    
    <foo:item>c</foo:item>
    
    <item>d</item>