使用递归来解析 Python 中的 Xml。返回值存在问题。

2024-10-04 11:24:57 发布

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

我对Python和编程有点陌生,所以我很抱歉。顺便说一下,谢谢。在

我正在使用Python2.5、cElementTree和expat解析一个xml文档(kml专门用于Google Earth)。我试图从每个“placemark”节点内的“name”、“description”和“coordinates”节点中提取每个几何体类型(即折线、多边形、点)的所有文本,但我希望保持几何体类型的独立性。例如,我只需要“name”、“description”和“coordinates”文本作为“polygon”的一部分(即它有一个“polygon”节点)。我将需要这样做的'折线'和'点'。我已经找到了一种方法来实现这一点,但是代码很冗长,而且针对每种几何类型都是特定的,这就引出了我的问题。在

理想情况下,我希望对每个几何体类型使用相同的代码,但问题是每个几何体类型都有不同的节点结构(即不同的节点名称和嵌套节点的数量)。因此,为了验证概念,我认为这是一个很好的机会,可以使用/学习递归来深入“placemark”节点的节点树并获得我要查找的信息。我看过很多关于Python递归的文章,但是在实现所提供的解决方案方面仍然存在问题。在

“placemark”节点的示例xml是:

 <Placemark>
    <name>testPolygon</name>
    <description>polygon text</description>
    <styleUrl>#msn_ylw-pushpin</styleUrl>
    <Polygon>
            <tessellate>1</tessellate>
            <outerBoundaryIs>
                    <LinearRing>
                            <coordinates>
                                    -81.4065,31.5072,0 -81.41269,31.45992,0 -81.34490,31.459696,0 
                            </coordinates>
                    </LinearRing>
            </outerBoundaryIs>
    </Polygon>
 </Placemark>

我使用的递归函数是:

^{pr2}$

我调用递归函数如下:

searchNode = 'coordinates'

# loop through all 'Placemark nodes' in document
for mark in placemark:

    # Get children of 'Placemark' node
    children = mark.getchildren() 

    # Loop through children nodes
    for child in children:

        # if a 'Polygon' node is found
        if child.tag == 'Polygon':

            # call recursion function
            getCoords( child, searchNode)

我知道,至少,我的部分问题是返回值。其他帖子建议返回该函数,我将其解释为“return getCoords(child,searchNode),但我得到了一个无休止的循环。另外,我意识到这可以张贴在地理信息系统网站上,但我认为这是一个更一般的编程问题。有什么想法吗?在


Tags: nameinchild类型节点编程descriptionxml
2条回答

使用递归,您需要关注基本情况和递归情况。 无论您的基本情况是什么,如果您希望能够从递归中收集信息,它们必须返回递归案例可以(而且更重要的是)使用的数据。类似地,您需要确保递归案例返回的数据可以相互使用。在

首先确定基本情况和递归情况。 基本情况是“叶”节点,没有子节点。在基本情况下,您只想返回一些数据,而不想再次调用递归函数。这就是他们所说的“备份堆栈”并防止无限递归的原因。 递归情况将要求您保存从一系列递归调用中收集的数据,这几乎就是您在for循环中所做的工作。在

我注意到你

# Recursive case: node has one or more child
if len( children ) >= 1 :
    # Loop through all the children
    for child in children:
        # call to recursion function
        getCoords( child, searchNode )

但是你怎么处理你的getCoords调用的结果呢?在

您可以将结果保存在某种数据结构中,您可以在for循环结束时返回,或者如果您不想保存结果本身,只需在到达基本情况1(成功搜索)时打印它,而不是返回它。因为现在你的基本情况1只是向上返回一个对结果没有任何作用的实例!所以试试看:

^{pr2}$

既然你的结果在一个列表中,并且你使用了extend()方法,那么你也必须让你的基本情况返回列表!在

# Base case 1: does not have children and is the 'searchNode'
elif len( children ) == 0 and child.tag == searchNode:
    # Return the text from the node, inside a list
    return [child.text]
# Base case 2: doesn't have children and does not match 'searchNode'
else:
    # Return empty list so your extend() function knows what to do with the result
    return []

最后应该只给你一个列表,你可能想把它存储在一个变量中。我刚刚把结果打印在这里:

searchNode = 'coordinates'
# loop through all 'Placemark nodes' in document
for mark in placemark:
    # Get children of 'Placemark' node
    children = mark.getchildren()
    # I imagine that getchildren() might return None, so check it
    # otherwise you'll get an error when trying to iterate on it
    if children:
        # Loop through children nodes
        for child in children:
            # if a 'Polygon' node is found
            if child.tag == 'Polygon':
                # call recursion function and print (or save) result
                print getCoords( child, searchNode)

当节点是searchNode时,不会对递归调用的结果执行任何操作。在

您需要将递归调用的结果聚合到节点的子节点,或者只使用print子级.text而不是回来子级.text. 在

相关问题 更多 >