0

我有一个名为 vs_origonal_M.xml 的主 xml 文件我想添加某个孩子的所有类型

<location>  
</location>
<location>
</location>
.
.
.
<location>
</location>

直到查看完所有文件。

我首先打开目录,然后列出目录中的所有文件并检查它们是否确实是 xml 文件,然后我要带走某个孩子。然后(这就是我卡住的地方)我需要打开主文件并将这个子文件插入到同名的最后一个子文件下面,最后完成后我需要保存主 xml 文件

这是代码:

# List the xml files in the directory
from xml.dom import minidom
from xml.etree import ElementTree as ET
import glob
import os
import sys


def is_xml(HART_filename):
 string_length = len(HART_filename)
 suffix = '.xml'
 if HART_filename.endswith(suffix):
    return True 
 else:
    return False 

#add the directory to the python script
os.chdir("c:/Users/ME/Documents/XML_Parasing_Python")

#List all the files in an array
xml_list = os.listdir("c:/Users/ME/Documents/XML_Parasing_Python")
print xml_list
xml_list_length = len(xml_list)
print xml_list_length
number = 1

for number in range(1,xml_list_length):
    string_length = len(xml_list[number])
    #print string_length
    print xml_list[number]
    #check to see if file is .xml
    if is_xml(xml_list[number]) == True: 
        xmldoc = minidom.parse(xml_list[number])
        reflist = xmldoc.getElementsByTagName('location')
        var_ref = reflist[0]
        print reflist[0].toxml()
        #Add to master .xml file
        tree = ET.parse('vs_original_M.xml')
        number += 1
    else:
        number += 1
        print 'wasn''t true'
4

1 回答 1

1

可能有更好的方法来做你真正想做的事——特别是,你真正的 XML 很有可能只有一个<locations>标签,所有<location>标签都在下面,所以根本没有理由搜索最后一个<location>标签……</ p>

但这就是你的做法。

os.chdir('c:/Users/ME/Documents/XML_Parasing_Python/')
origname = 'vs_original_M.xml'
master = ET.parse(origname)
for path in os.listdir('.'):
    if path != origname and os.path.splitext(path)[-1] == '.xml':
        child = ET.parse(path)
        root = child.getroot()
        last_location_parent = master.find('.//*[{}][last()]'.format(root.tag))
        last_location_parent.append(root)
master.write('master.xml')

其中大部分都很简单。您必须找到最后一个节点的父location节点,然后才能找到append另一个节点。

唯一棘手的一点是 中的XPath表达式find,所以让我为您分解它(但您必须阅读文档才能真正理解它!):

  • .//表示“当前节点的后代”。(从技术上讲,您应该能够只//用于“根的后裔”,但在早期版本的 etree 中存在错误,因此这种方式更安全。)
  • *表示“使用任何标签名称”。
  • [location]意思是“带有一个子”位置“标签。(当然我是用format方法填写孩子的根标签。如果你知道你所有的孩子都有location作为根,你可以硬编码标签名称,并find移出也是循环的。)
  • [last()]意思是“最后一个”。

所以,把它们放在一起,这是根的最后一个带有子“位置”标签的名字的后代。


如果你不了解 XPath,你总是可以手动迭代东西以获得相同的效果,但是它会更长,并且更容易引入细微的错误,所以真的值得学习 XPath。


我在您的程序中更改了许多其他内容。让我解释:

没有理由这样做if foo: return True else: return False;你可以做return foo。但这意味着你的整个函数只是return HART_filename.endswith('.xml'),所以你甚至不需要一个函数。最好使用路径函数,os.path.splitext而不是路径上的字符串函数。

如果你这样做for number in range(1, xml_list_length),你不需要number = 1在开始和number += 1循环中;该for声明已经为您做到了。

但是您无论如何都不想从 1 开始;Python 列表的索引从 0 开始。如果你用它来跳过vs_original_M.xml,那只有在你幸运的情况下才有效;listdir返回事物的顺序是未指定且任意的。跳过具有特定名称的文件的唯一方法是检查其名称。

你几乎从不想循环range(len(foo))。如果你只需要 的元素foo,就去做for element in foo。如果您还需要每个元素的索引,请执行for index, element in enumerate(foo).

最后,您几乎不应该检查if foo == True. True在 Python 中,除了(数字74、字符串“hello”等)之外,很多东西都是“真实的”,你可以只用它if foo来检查 foo 是否真实。仅== True在您明确要确保它失败或其他真实值时使用;如果您只想检查is_xmlendswith==运算符之类的布尔函数的结果,只需直接检查即可。

于 2013-08-26T17:38:41.750 回答