2013-06-20 190 views
0

以下是我的python(2.6)脚本遇到的两个不同文件。一个会解析,另一个不会。我只是好奇为什么会发生这种情况。元素树以不同的方式处理相似的文件

这个XML文件将无法解析和脚本会失败:

<Landfire_Feedback_Point_xlsform id="fbfm40v10" instanceID="uuid:9e062da6-b97b-4d40-b354-6eadf18a98ab" submissionDate="2013-04-30T23:03:32.881Z" isComplete="true" markedAsCompleteDate="2013-04-30T23:03:32.881Z" xmlns="http://opendatakit.org/submissions"> 
<date_test>2013-04-17</date_test> 
<plot_number>10</plot_number> 
<select_multiple_names>BillyBob</select_multiple_names> 
<geopoint_plot>43.2452830500 -118.2149402900 210.3000030518 3.0000000000</geopoint_plot><fbfm40_new>GS2</fbfm40_new> 
<select_grazing>NONE</select_grazing> 
<image_close>1366230030355.jpg</image_close> 
<plot_note>No road present.</plot_note> 
<n0:meta xmlns:n0="http://openrosa.org/xforms"> 
<n0:instanceID>uuid:9e062da6-b97b-4d40-b354-6eadf18a98ab</n0:instanceID> 
</n0:meta> 
</Landfire_Feedback_Point_xlsform> 

这个XML文件将正确地分析和脚本成功:

<Landfire_Feedback_Point_xlsform id="fbfm40v10"> 
<date_test>2013-05-14</date_test> 
<plot_number>010</plot_number> 
<select_multiple_names>BillyBob</select_multiple_names> 
<geopoint_plot>43.26630563 -118.39881809 351.70001220703125 5.0</geopoint_plot> 
<fbfm40_new>GR1</fbfm40_new> 
<select_grazing>HIGH</select_grazing> 
<image_close>fbfm40v10_PLOT_010_ID_6.jpg</image_close> 
<plot_note>Heavy grazing</plot_note> 
<meta><instanceID>uuid:90e7d603-86c0-46fc-808f-ea0baabdc082</instanceID></meta> 
</Landfire_Feedback_Point_xlsform> 

这里是一个小的Python脚本,它表明,一个会工作,而另一个不会。我只是寻找一个解释,为什么一个被ElementTree视为一个XML文件,而另一个不是。具体来说,似乎没有解析失败的一个“NONE”类型没有“文本”属性“或类似的东西。但是,这是因为它似乎没有将文件视为xml,或者它看不到任何超出开始行的元素。任何关于这个错误的解释或指导将不胜感激。提前致谢。

Python脚本:

import os 
from xml.etree import ElementTree 


def replace_xml_attribute_in_file(original_file,element_name,attribute_value): 
    #THIS FUNCTION ONLY WORKS ON XML FILES WITH UNIQUE ELEMENT NAMES 
    # -DUPLICATE ELEMENT NAMES WILL ONLY GET THE FIRST ELEMENT WITH A GIVEN NAME 

    #split original filename and add tempfile name 
    tempfilename="temp.xml" 
    rootsplit = original_file.rsplit('\\') #split the root directory on the backslash 
    rootjoin = '\\'.join(rootsplit[:-1]) #rejoin the root diretory parts with a backslash -minus the last 
    temp_file = os.path.join(rootjoin,tempfilename) 
    et = ElementTree.parse(original_file) 
    author=et.find(element_name) 
    author.text = attribute_value 
    et.write(temp_file) 
    if os.path.exists(temp_file) and os.path.exists(original_file): #if both the original and the temp files exist 
     os.remove(original_file)         #erase the original 
     os.rename(temp_file,original_file)       #rename the new file 
    else: 
     print "Something went wrong." 

replace_xml_attribute_in_file("testfile1.xml","image_close","whoopdeedoo.jpg"); 
+0

是什么让你觉得它不是把第二个视为XML,或者在第一行之后停止,或者其他什么?当我把你的第一个例子和'print et.getroot()。getchildren()',它为我提供了9个子节点,因此显然它将它视为XML,并不仅仅是一行。那么......你的实际问题是什么?它对你有不同的表现吗?或者,例如,“find”找不到任何东西,你只是假设它意味着它不解析任何东西而不是检查? – abarnert

+1

此外,在未来,不要试图模糊地描述你的错误;粘贴实际的错误追踪。 – abarnert

回答

0

这里是一个小Python脚本,证明了一会的工夫,而其他则不会。我只是寻找一个解释,为什么一个被ElementTree视为一个XML文件,而另一个不是。

您的代码根本没有证明。这表明它们都被ElementTree看作是有效的XML文件,充满了节点。他们都解析得很好,他们都读过第一行,等等。

唯一的问题是,第一个没有名为'image_close'的节点,所以你的代码不起作用。

你可以看到,很容易地:

for node in et.getroot().getchildren(): 
    print node.tag 

你得到根本的9个孩子,有两个版本。

而输出到这应该告诉你的问题。您需要的节点在第一个示例中实际上命名为{http://opendatakit.org/submissions}image_close,而不是第二个中的image_close

而且,正如您大概猜测的那样,这是因为根节点中的namespace=http://opendatakit.org/submissions。 ElementTree使用"James Clark notation"将未知名称空间名称映射到通用名称。

无论如何,因为没有节点被命名为image_close,该et.find(element_name)回报None,让你的代码存储author=None,然后尝试分配给author.text,并得到一个错误。

至于如何解决这个问题...你可以学习如何命名空间默认在ElementTree中工作,或者你可以升级到Python 2.7或安装一个更新的ElementTree for 2.6,让你更容易地自定义事情。但是,如果你想做自定义的命名空间处理,并坚持你的旧版本...我会从this article(及其两个前任)和this one开始。

+0

“你可以很容易地看到:” “而且,正如你大概猜测的那样,” Crackin让我知道了所有这些。无论如何,我真的很感谢这个帮助,尽管我对XML一无所知(只是很危险),而我当然不知道“命名空间”是什么或者元素和节点之间的区别。但是,在阅读您的回复几次之后,我想我可以闻到您收到的内容。我真的很感谢帮助和理解。我会阅读....并使事情可行。感谢你的理智。 – user2507101

+0

_right_解决方案非常需要理解XML命名空间,以及ET如何处理它们,这是一个很大的学习。如果你只是想要一个快速和肮脏的黑客攻击,你可以只打印一次,记录ET给你的节点名称,并相应地搜索 - 例如,使用“{http://opendatakit.org/submissions}image_close”'而不是'“image_close”',或者使用'et.find(“{http://opendatakit.org/submissions}”+ element_name)''。这绝对是不吉利的,但如果今天让你度过今天的问题,那么可能值得考虑。 – abarnert

相关问题