2012-01-30 7 views
5

--- Update 3: Ho lo script per aggiornare i dati richiesti nei file xml completati ma il codice seguente viene eliminato dal file scritto. Perchè è questo? come posso sostituirlo?Cerca e sostituisci più righe in file xml/di testo usando python

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

Codice di lavoro corrente (tranne per il problema menzionato sopra).

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) 

--- Update 1 & 2: Grazie a Aleyna Ho il seguente codice di base che funziona

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) 

Il problema è di trattare con il codice XML come

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

Poiché la parola chiave thes ... non è univoca all'interno dello <spdom>, possiamo aggiornarli in un ordine dai valori provenienti da

FileDesc_obj.spatialReference.name 

u'GCS_GDA_1994'

--- post originale ---

Sto costruendo un programma per generare file metadati XML da file spaziali nella nostra biblioteca. Ho già creato gli script per estrarre i dati spaziali e di attributo richiesti dai file e creare un indice di file shp e di testo basato sui file, ma ora voglio scrivere queste informazioni sul file XML di metadati di base che viene scritto in standard anzlic sostituendo i valori detenuti da elementi comuni/static ...

Così, per esempio voglio sostituire il seguente codice XML

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

con

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

il problema è che, ovviamente, il numero/valore di tra e non sarà lo stesso.

Analogamente per tag xml come <title>, <nondig><formname> ecc ... nel secondo esempio entrambi i tag devono essere cercati insieme poiché il nome del modulo appare più volte (non è univoco).

Sto usando il Python Regular Expression manuale [qui] [1],

+1

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

+0

grazie ... Non sto provando a scrivere un file xml da zero. Voglio solo sostituire pezzi di testo all'interno di determinati attributi in base all'input del modulo arcpy. – GeorgeC

+1

Quindi quando produce un output che assomiglia a ' 8097970', il tuo regex lo gestirà? – Borealid

risposta

2

Utilizzando i tag specificati sopra:

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) 

Qui, XPATH .//northbc restituisce tutti i nodi 'northbc' nel doc XML. È possibile personalizzare il codice per le proprie esigenze facilmente.

+0

Grazie, ma ho il seguente ... >> path = os.getcwd() >> albero = et.parse (percorso) Traceback (chiamata più recente scorso): file "C: \ Program Files (x86) \ Wing IDE 101 4.0 \ src \ debug \ tserver \ _sandbox.py", linea 1, in # Utilizzato internamente per debug sandbox con interprete esterno File "C: \ Python26 \ ArcGIS10.0 \ Lib \ xml \ etree \ ElementTree.py", riga 862, in parse tree.parse (origine, parser) File "C: \ Python26 \ ArcGIS10.0 \ Lib \ xml \ etree \ ElementTree.py ", riga 579, in parse source = open (source," rb ") IOError: [ Errno 13] Autorizzazione negata: 'L: \\ Data_Admin \\ QA \\ Metadata_python_toolset \\ training' – GeorgeC

+0

Si prega di NON CONSEGNARE il mio commento precedente. Funziona bene quando path è un vero file xml. Cosa faresti con i tag ripetuti come il terzo esempio - '' dove il nome del modulo viene ripetuto ma non è univoco. – GeorgeC

+0

Se ho capito bene, hai più s figli diretti di univoci nodi ? Quindi è possibile utilizzare tale percorso .//nondig/formname per ottenere s. Puoi salire sull'albero e controllare il genitore prima di sostituire il valore o, ancora meglio, puoi riscrivere il tuo xpath usando l'attr di genitore (forse un id?) In modo che s siano raggruppati per s. – Aleyna

0

potrei essere affermare l'ovvio qui, ma lo considerare l'utilizzo di un albero DOM per analizzare e manipolare il vostro XML?

1

Se si ha a che fare con XML valido, utilizzare XPath per trovare i nodi di interesse e l'API ElementTree per manipolare il nodo.

Ad esempio, il tuo xpath potrebbe essere qualcosa come "// northbc" e dovrai semplicemente sostituire il nodo di testo al suo interno.

Vedere http://docs.python.org/library/xml.etree.elementtree.html e http://pypi.python.org/pypi/lxml/2.2.8 per due diverse librerie che consentono di ottenere questo risultato.Cerca google per XPath e guarda il tutorial di w3c per una decente introduzione a XPath (apparentemente non posso pubblicare più di due link in un post o lo collegherei anch'io)

+0

grazie. Questo sembra sulla strada giusta e sto passando attraverso http://www.w3schools.com/xpath/ – GeorgeC

Problemi correlati