2012-01-30 43 views
5

--- Actualización 3: Tengo la secuencia de comandos para actualizar los datos requeridos en los archivos xml completados, pero el siguiente código se descarta del archivo escrito. ¿Por qué es esto? ¿cómo puedo reemplazarlo?Buscar y reemplazar varias líneas en archivos xml/texto usando python

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

Código de trabajo actual (excepto por el problema mencionado anteriormente).

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) 

--- Actualización 1 & 2: Gracias a Aleyna Tengo el siguiente código básico que funciona

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) 

El problema es con el trato con el código XML como

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

Como la palabra clave thes ... no es única dentro de <spdom> podemos actualizar estos en un orden de los valores provenientes de

FileDesc_obj.spatialReference.name 

u'GCS_GDA_1994'

--- --- post original

estoy construyendo un programa para generar archivos XML de metadatos de los archivos espaciales en nuestra biblioteca. Ya he creado las secuencias de comandos para extraer los datos espaciales y alterados requeridos de los archivos y crear un archivo basado en archivos shp y de texto de los archivos, pero ahora quiero escribir esta información en el archivo base metadata xml que se escribe en estándares anzlic reemplazando los valores de los elementos comunes/estáticas ...

Así, por ejemplo, que quieren reemplazar el siguiente código XML

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

con

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

la cuestión es que, obviamente, el número/valor entre y no será lo mismo.

De forma similar para las etiquetas xml como <title>, <nondig><formname> etc ... en el último ejemplo ambas etiquetas deben buscarse juntas ya que formname aparece varias veces (no es único).

estoy usando el pitón manual de expresiones regulares [aquí] [1],

+1

Ver http://stackoverflow.com/a/1732454/383402 – Borealid

+0

gracias ... No estoy tratando de escribir un archivo XML desde cero. Solo quiero reemplazar trozos de texto dentro de atributos dados basados ​​en la entrada del módulo arcpy. – GeorgeC

+1

Así que cuando se produce una salida que se parece a ' 8097970 ', su expresión regular manejarlo? – Borealid

Respuesta

2

Usando la (s) etiqueta (s) indicada (s) arriba:

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) 

Aquí, XPATH .//northbc devuelve todos los nodos '' northbc en el documento XML. Puede adaptar el código para su necesidad fácilmente.

+0

Gracias pero obtengo lo siguiente ... >> path = os.getcwd() >> tree = et.parse (ruta) Traceback (última llamada más reciente): Archivo "C: \ Archivos de programa (x86) \ Wing IDE 101 4.0 \ src \ debug \ tserver \ _sandbox.py", línea 1, en # Usado internamente para depuración de sandbox bajo intérprete externo Archivo "C: \ Python26 \ ArcGIS10.0 \ Lib \ xml \ etree \ ElementTree.py", línea 862, en el análisis tree.parse (fuente, analizador) Archivo "C: \ Python26 \ ArcGIS10.0 \ Lib \ xml \ etree \ ElementTree.py", línea 579, en análisis sintáctico fuente = abierto (fuente, "rb") IOError: [ Errno 13] Permiso denegado: 'L: \\ Data_Admin \\ QA \\ Metadata_python_toolset \\ training' – GeorgeC

+0

Por favor, DISCRETA mi comentario anterior. Funciona bien cuando path es un archivo xml real. ¿Qué haría con repetir etiquetas como el 3er ejemplo? '' donde formname se repite pero nondig es único. – GeorgeC

+0

Si lo estoy haciendo bien, tiene múltiples s que son hijos directos de nodos únicos ? Entonces puede usar dicho xpath .//nondig/formname para obtener s. Puede Walt arriba en el árbol y comprobar el padre antes de cambiar el valor o mejor aún puede volver a escribir su XPath utilizando attr única de los padres (tal vez un id?) Para que s se agruparán por s. – Aleyna

0

Puede ser que sea una obviedad aquí, pero tenía que considerar el uso de un árbol DOM para analizar y manipular el código XML?

1

Si se trata de XML válido, utilice XPath para buscar los nodos de interés y ElementTree api para manipular el nodo.

Por ejemplo, su xpath podría ser algo así como '// northbc' y simplemente reemplazaría el nodo de texto dentro de él.

Consulte http://docs.python.org/library/xml.etree.elementtree.html, así como http://pypi.python.org/pypi/lxml/2.2.8 para obtener dos bibliotecas diferentes que lo ayudarán a hacer esto.Busque en Google XPath y vea el tutorial de w3c para obtener una introducción decente a XPath (aparentemente no puedo publicar más de dos enlaces en una publicación o lo vincularé también)

+0

gracias. Esto parece estar en el camino correcto y estoy repasando http://www.w3schools.com/xpath/ – GeorgeC

Cuestiones relacionadas