使用Python在XML/文本文件中搜索替换多行

5 投票
3 回答
4376 浏览
提问于 2025-04-17 11:55

---更新 3:

我已经完成了一个脚本,可以把需要的数据更新到xml文件里,但写入的文件中有一段代码却没有被包含进去。这是为什么呢?我该怎么替换它呢?

<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='ANZMeta.xsl'?>

目前的代码可以正常工作(除了上面提到的问题)。

import os, xml, arcpy, shutil
from xml.etree import ElementTree as et 

path=os.getcwd()
arcpy.env.workspace = path

FileList = arcpy.ListFeatureClasses()
FileCount = len(FileList)
zone="_Zone"

for File in FileList:
    FileDesc_obj = arcpy.Describe(File)
    FileNm=FileDesc_obj.file
    newMetaFile=FileNm+"_BaseMetadata.xml"

    check_meta=os.listdir(path)
    if FileNm+'.xml' in check_meta:
        shutil.copy2(FileNm+'.xml', newMetaFile)
    else:
        shutil.copy2('L:\Data_Admin\QA\Metadata_python_toolset\Master_Metadata.xml', newMetaFile)
    tree=et.parse(newMetaFile)

    print "Processing: "+str(File)

    for node in tree.findall('.//title'):
        node.text = str(FileNm)
    for node in tree.findall('.//northbc'):
        node.text = str(FileDesc_obj.extent.YMax)
    for node in tree.findall('.//southbc'):
        node.text = str(FileDesc_obj.extent.YMin)
    for node in tree.findall('.//westbc'):
        node.text = str(FileDesc_obj.extent.XMin)
    for node in tree.findall('.//eastbc'):
        node.text = str(FileDesc_obj.extent.XMax)        
    for node in tree.findall('.//native/nondig/formname'):
        node.text = str(os.getcwd()+"\\"+File)
    for node in tree.findall('.//native/digform/formname'):
        node.text = str(FileDesc_obj.featureType)
    for node in tree.findall('.//avlform/nondig/formname'):
        node.text = str(FileDesc_obj.extension)
    for node in tree.findall('.//avlform/digform/formname'):
        node.text = str(float(os.path.getsize(File))/int(1024))+" KB"
    for node in tree.findall('.//theme'):
        node.text = str(FileDesc_obj.spatialReference.name +" ; EPSG: "+str(FileDesc_obj.spatialReference.factoryCode))
    print node.text
    projection_info=[]
    Zone=FileDesc_obj.spatialReference.name

    if "GCS" in str(FileDesc_obj.spatialReference.name):
        projection_info=[FileDesc_obj.spatialReference.GCSName, FileDesc_obj.spatialReference.angularUnitName, FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName]
        print "Geographic Coordinate system"
    else:
        projection_info=[FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName, FileDesc_obj.spatialReference.angularUnitName, Zone[Zone.rfind(zone)-3:]]
        print "Projected Coordinate system"
    x=0
    for node in tree.findall('.//spdom'):
        for node2 in node.findall('.//keyword'):
            print node2.text
            node2.text = str(projection_info[x])
            print node2.text
            x=x+1


    tree.write(newMetaFile)

---更新 1和2:

多亏了Aleyna,我得到了以下基本代码,它可以正常运行。

import os, xml, arcpy, shutil
from xml.etree import ElementTree as et 

CodeString=['northbc','southbc', '<nondig><formname>']

nondig='nondigital'
path=os.getcwd()
arcpy.env.workspace = path
xmlfile = path+"\\test.xml"

FileList = arcpy.ListFeatureClasses()
FileCount = len(FileList)

for File in FileList:
    FileDesc_obj = arcpy.Describe(File)
    FileNm=FileDesc_obj.file
    newMetaFile=FileNm+"_Metadata.xml"
    shutil.copy2('L:\Data_Admin\QA\Metadata_python_toolset\Master_Metadata.xml', newMetaFile)
    tree=et.parse(newMetaFile)

    for node in tree.findall('.//northbc'):
        node.text = str(FileDesc_obj.extent.YMax)
    for node in tree.findall('.//southbc'):
        node.text = str(FileDesc_obj.extent.YMin)
    for node in tree.findall('.//westbc'):
        node.text = str(FileDesc_obj.extent.XMin)
    for node in tree.findall('.//eastbc'):
        node.text = str(FileDesc_obj.extent.XMax)        
    for node in tree.findall('.//native/nondig/formname'):
        node.text = nondig

    tree.write(newMetaFile)

问题出在处理像这样的xml代码上:

- <spdom>
  <keyword thesaurus="">GDA94</keyword> 
  <keyword thesaurus="">GRS80</keyword> 
  <keyword thesaurus="">Transverse Mercator</keyword> 
  <keyword thesaurus="">Zone 55 (144E - 150E)</keyword> 
  </spdom>

因为关键字“thes...在<spdom>中并不是唯一的,我们能否按照来自以下值的顺序更新这些内容:

FileDesc_obj.spatialReference.name

u'GCS_GDA_1994'

---原始帖子---

我正在建立一个程序,从我们库里的空间文件生成xml元数据文件。我已经创建了脚本,从文件中提取所需的空间和属性数据,并创建了一个shp和文本文件的索引,但现在我想把这些信息写入一个基础的元数据xml文件,这个文件是按照anzlic标准写的,通过替换一些公共或静态元素的值……

举个例子,我想替换以下的xml代码:

<northbc>8097970</northbc>
<southbc>8078568</southbc>

为:

<northbc> GeneratedValue_[desc.extent.XMax] /<northbc>
<southbc> GeneratedValue_[desc.extent.XMax] </southbc>

问题是,显然<tag></tag>之间的数字或值不会是相同的。

同样,对于像<title>、<nondig>、<formname>这样的xml标签……在后面的例子中,这两个标签必须一起搜索,因为formname出现了多次(并不是唯一的)。

我正在使用Python正则表达式手册[在这里][1]。

3 个回答

0

我可能说的很明显,但你有没有考虑过用DOM树来解析和处理你的XML呢?

1

如果你在处理有效的XML文件,可以使用XPath来找到你感兴趣的节点,然后用ElementTree这个工具来操作这些节点。

比如,你的XPath可能是'//northbc',然后你只需要替换里面的文本节点就可以了。

你可以查看这个链接这个链接,这两个库可以帮助你完成这个任务。你也可以在谷歌上搜索XPath,看看w3c的教程,那里有个不错的XPath入门介绍(我好像不能在一条帖子里放超过两个链接,要不然我也会链接那个教程)。

2

使用上面给出的标签:

import os
import xml
from xml.etree import ElementTree as et 
path = r"/your/path/to/xml.file" 
tree = et.parse(path)
for node in tree.findall('.//northbc'):
    node.text = "New Value"
tree.write(path)

在这里,XPATH .//northbc 会返回XML文档中所有的'northbc'节点。你可以很容易地根据自己的需求调整这段代码。

撰写回答