2016-08-31 4 views
-2

Ich musste 500 Kopien einer XML-Datei in dem Verzeichnis erstellen, was ich fertig brachte. Als Teil des nächsten Problems möchte ich einen bestimmten Text in der Datei umbenennen. Wie kann ich es tun?Benennen Sie eine bestimmte Instanz in mehreren Dateien mit dem Dateinamen um?

Das ist, was ich habe: 1000.xml, 1001.xml, 1002.xml ...

1000.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation='test.xsd'> 
<address> 
    <name>Joe Tester</name> 
    <street>Baker street 5</street> 
    <id>1000</id> 
</address> 
<count>1000</count> 

Im Wesentlichen wird dies kopiert alle anderen Dateien, aber mit einem numerischen und chronologischen Namen. Wie ersetze ich dieses "1000" durch den "Dateinamen"? So sollte die neue Datei sein - 1001.xml:

<?xml version="1.0" encoding="UTF-8"?> 
    <addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation='test.xsd'> 
    <address> 
     <name>Joe Tester</name> 
     <street>Baker street 5</street> 
     <id>1001</id> 
    </address> 
    <count>1001</count> 
</addresses> 

Ich konnte dies nur - sed -i '' -e 's/1000/1001/g' $(find . -type f), die alle die 1000 mit 1001 ersetzen werden, aber nicht die Dateinamen.

+1

Und was hast du bisher versucht? Dies scheint eine ziemlich einfache Shell-Skriptaufgabe zu sein. Vielleicht eine 'for' Schleife? – larsks

+0

Ich postete den sed-Befehl, den ich mir vorstellen konnte. Aber es benennt alle 1000 zu 1001. Es sollte jedoch 1002 in Datei 1002.xml, 1003 in 1003.xml und so weiter sein. – Metahuman

Antwort

2

Nach entziffern Ihre Frage, die ich sehe Sie wünschen Wenn Sie tatsächlichen Inhalt in der XML-Datei zu ändern, dh die ID oder einen anderer Knoten Text auf den Namen der Datei, so einen XML-Parser verwenden, wie lxml

from glob import iglob 
import lxml.etree as et 

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
    tree = et.parse(fle) 
    id_ = tree.find(".//id").text = fle 
    tree.write(fle, encoding="utf-8") 

wollen die Zählung auch verwenden, um zu ändern:

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
     tree = et.parse(fle) 
     id_, count = tree.find(".//id"), tree.find(".//count") 
     id_.text = count.text = fle 
     tree.write(fle, encoding="utf-8") 

, was Text Sie auf den Dateinamen für den Knoten nur schauen mit find festlegen möchten, und setzen verwenden Sie den Text der node.text = ... Logik. Wenn Sie den Namen ignorieren die Erweiterung nur Split verwenden möchten:

for fle in iglob("[0-9][0-9][0-9][0-9].xml"): 
     tree = et.parse(fle) 
     id_, count = tree.find(".//id"), tree.find(".//count") 
     id_.text = count.text = fle.split(".")[0] 
     tree.write(fle, encoding="utf-8") 
+0

Danke Padraic. Wie bearbeite ich den Dateiinhalt in id, zähle auf den Dateinamen? – Metahuman

+0

@ Metahuman, das ist, was das zweite Schnipsel tut, folgen Sie ihm mit 'tree.write (fle, encoding =" utf-8 ")' und es wird die neuen Daten schreiben, editierte ich die Antwort. –

+0

Willst du nur ersetzen, um die 1000 durch 1001 usw. zu ersetzen ... oder den vollständigen Dateinamen verwenden? –

1

Versuchen Sie, sed Befehl in einer schlaufen

for i in {1000..1500} #or whatever your maximum number is 
do 
sed -i "s/1000/"$i"/g" "$i".xml 
done 
+1

Ich bin mir wirklich nicht sicher, ob das eine gute Lösung ist. Es funktioniert, aber .... die Handhabung von XML, ohne es zu analysieren, ist im besten Fall immer ziemlich hacky. – Sobrique

+0

Wenn Sie wissen, dass der Kontext immer die Brokets enthalten wird, vielleicht tun "" s /> 1000 $ i tripleee

3

haben Sie es markiert perl so hier ist, wie ich es tun würde:

#!/usr/bin/perl 
use strict; 
use warnings; 

use XML::Twig; 
#iterate the files. 
foreach my $xml_file (glob "*.xml") { 
    #regex match the number for the XML. 
    my ($file_num) = $xml_file =~ m/(\d+).xml/; 
    #create an XML::Twig, and set it to 'indented' output. 
    XML::Twig -> new (pretty_print => 'indented', 
      #matches elements and runs the subroutine on 'it'. ($_) is the 
      #current element in this context. 
         twig_handlers => { 'address/id' => sub { $_ -> set_text($file_num) }, 
              'count'  => sub { $_ -> set_text($file_num) }, 
      #parsefile_inplace reads and writes back any changes to the file 
      #as it goes. 
             }) -> parsefile_inplace($xml_file); 


} 

Dies verwendet XML::Twig, die Sie ein an Ort und Stelle bearbeiten tun können. Dies geschieht über die Element-Handler, die bei einer passenden Übereinstimmung den Inhalt durch den richtigen numerischen Wert für die Datei ersetzen.

Ich habe entschieden, den definierten Inhalt für address/id und count, anstatt nur zu ersetzen, tut gerade suchen und ersetzen, denn dann ... Sie müssen nicht über 1000 Sorge irgendwo sonst auf dem Inhalt auftauchen. (Wie die Adresse).

+0

Vielen Dank! Das funktioniert! – Metahuman

Verwandte Themen