簡體   English   中英

使用遞歸與Python進行XML解析。 返回值問題

[英]Xml parsing with Python using recursion. Problem with return value

我對Python和一般編程還是有些陌生,所以我深表歉意。 順便說一句,在此先感謝。

我正在使用Python 2.5,cElementTree和expat解析xml文檔(專門用於Google Earth的kml)。 我試圖從每種幾何類型(即折線,多邊形,點)的每個“地標”節點中的“名稱”,“描述”和“坐標”節點中提取所有文本,但我想保留這些幾何類型分離。 例如,對於作為“多邊形”一部分(即它具有“多邊形”節點)的每個地標,我只需要“名稱”,“描述”和“坐標”文本。 我還需要針對“折線”和“點”執行此操作。 我已經找到了一種方法,但是代碼很冗長,並且特定於每種幾何類型,這導致了我的問題。

理想情況下,我想對每種幾何類型使用相同的代碼,但是問題是每種幾何類型具有不同的節點結構(即,不同的節點名稱和嵌套節點的數量)。 因此,為了概念驗證,我認為這將是使用/學習遞歸來深入研究“地標”節點的節點樹並獲取我正在尋找的信息的好機會。 我看過許多有關Python遞歸的文章,但在實現所提供的解決方案時仍然遇到問題。

“地標”節點的示例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>

我正在使用的遞歸函數是:

def getCoords( child, searchNode ):

    # Get children of node
    children = child.getchildren()

    # If 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 )

    # If does not have children and is the 'searchNode'
    elif len( children ) == 0 and child.tag == searchNode:

        # Return the text inside the node. This is where it is not working    
        # Other posts recommended returning the function like 
        # return getCoords(child, searchNode), but I am getting an unending loop
        return child.text

    # Do nothing if node doesn't have children and does not match 'searchNode'    
    else: 

        print 'node does not have children and is not what we are looking for'

我正在調用遞歸函數,如:

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)

我至少知道部分問題是返回值。 其他帖子建議返回該函數,我將其解釋為“返回getCoords(child,searchNode),但我遇到了無休止的循環。 另外,我意識到這可以發布在GIS網站上,但是我認為這更多是一個通用的編程問題。 有任何想法嗎?

使用遞歸時,您要注意基本情況和遞歸情況。 無論您遇到的基本案例是什么,如果您希望能夠從遞歸中收集信息,則它們必須返回遞歸案例可以(並且更重要的是可以使用)的數據。 同樣,您需要確保遞歸案例返回的數據可以相互使用。

首先確定您的基礎案例和遞歸案例。 基本情況是“葉”節點,沒有子節點。 在基本情況下,您只想返回一些數據,而不要再次調用遞歸函數。 這就是使您能夠像他們所說的那樣“備份堆棧”並防止無限遞歸的方法。 遞歸情況將需要您保存從一系列遞歸調用中收集的數據,這幾乎是您在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只是將堆棧返回到對結果不做任何事的實例! 因此,請嘗試:

# If node has one or more child
if len( children ) >= 1 :
    # Data structure for your results
    coords = []
    # Loop through all the children
    for child in children:
        # call to recursion function
        result = getCoords( child, searchNode )
        # Add your new results together
        coords.extend(result)
    # Give the next instance up the stack your results!
    return coords

現在,由於您的結果在列表中,並且使用了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 child.text而不是return child.text。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM