XML-Tag-Vergleich

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hallo zusammen,

ich würde gerne XML-Files verschiedener Sprachen miteinander vergleichen, und diejenigen, welche einander entsprechen, in einer Liste ausgeben.
Da sich oftmals sogar die Autorennamen je nach Sprache unterscheiden können, scheint mir die Websiteangabe (also die Verlinkung) die verlässlichste Quelle zu sein, um zwei XMLs zu vergleichen.
Nun meine Frage: Wie kann ich File 1 der einen Sprache nehmen, schauen, was im Tag "<filename>" steht, und dann durch all die andere Files einer anderen Sprache gehen und dort nach dem gleichen Taginhalt zu suchen?

Danke für jede Hilfe! :)
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Stammen die XML-Dateien alle aus der selben Quelle oder sind sie ein wild zusammengewürfelter Haufen von unterschiedlichen Portalen (oder wie auch immer man das nennen möchte)? Mit anderen Worten: Sind zum Beispiel die Bezeichnungen für die Tags und die Reihenfolge ihres Auftretens immer gleich und nur der Text, den sie umschließen, ist in unterschiedlichen Sprachen verfasst?
BlackJack

@MarcelF6: Was ist denn jetzt konkret das Problem? Schreib 'ne Funktion die Dir das <filename>-Tag sucht und den Text extrahiert, mach das mit der XML-Datei für eine Sprache und dann iteriere in einer Schleife über die XML-Dateien für die anderen Sprachen, wende die Funktion an und vergleiche jeweils das Ergebnis.

Die Beschreibung „XML-Datei für eine Sprache” und „Autorennamen” sind ein wenig wenig ohne weitere Erklärungen, denn das ist beides nichts was ganz allgemein für XML-Dateien gilt, sondern anscheinend spezifisch für Deine XML-Anwendung.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Die Frage ist jetzt wirklich Dein Ernst? Du hast doch schon in so vielen Threads etwas zu XML gefragt... da solltest Du doch mittlerweile in der Lage sein, eine Datei zu öffnen, den XML-Baum zu parsen, zu bestimmten Knoten navigieren und auch durch die Struktur zu iterieren‽

Im Grunde kann man zu Deiner sehr allgemein gestellten Frage wenig mehr sagen. Finde den Knoten ``<filename>`` im ersten Baum, iteriere über den zweiten und suche ein passendes Tag, vergleiche beide Tag-Inhalte.

Wo genau liegt denn das Problem?

(Im übrigen wird der Kontext nicht wirklich klar. Was ist die "Sprache" einer XML-Datei?)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

MarcelF6 hat geschrieben:Wie kann ich File 1 der einen Sprache nehmen, schauen, was im Tag "<filename>" steht, und dann durch all die andere Files einer anderen Sprache gehen und dort nach dem gleichen Taginhalt zu suchen?
Nimm einen Parser, der XPath versteht und suche dir dann den entsprechenden Text raus. In XPath wirst du dich ggf etwas einlesen müssen. Allzu kompliziert ist diese Sprache aber eigentlich nicht.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Ich habs mit etree gemacht.
Folgendes habe ich schon, ich frage mich nur, wie man den Durchlauf durch die Verzeichnisse (und den gesamten Code) etwas eleganter gestalten könnte.
Ich würde einfach zwei for-Schleifen verschachteln: Die erste fürs DE, die zweite fürs FR. Oder gibt es da eine andere Möglichkeit?
Danke für die Hilfe!

Code: Alles auswählen

mainXml = ET.parse("/home/XML/2012/01/d/d_2012_01_01.xml") 
root = mainXml.getroot()
img = root.find("images/image")
for child in img:
    if child.tag == "file_name":
        txtDE = child.text

FRXml = ET.parse("/home/XML/2012/01/f/f_2012_01_01.xml")
rootFR = FRXml.getroot()
imgFR = rootFR.find("images/image")
for child in imgFR:
    if child.tag == "file_name":
        txtFR = child.text
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Guck Dir doch mal Deinen Code rein optisch an! Das ist zwei mal fast vollständig identisch, von den Namen einmal abgesehen. So etwas kann man doch *sehr* einfach in eine Funktion kapseln:

Code: Alles auswählen

def get_file_name(filename):
    mainXml = ET.parse(filename)
    root = mainXml.getroot()
    img = root.find("images/image")
    for child in img:
        if child.tag == "file_name":
            return child.text

default_name = get_file_name("/home/XML/2012/01/d/d_2012_01_01.xml")
fr_name = get_file_name("/home/XML/2012/01/f/f_2012_01_01.xml")
Wenn Du nun eine Liste von XML-Dateien hast, so kannst Du die Funktion auch in einer Schleife über der Liste aufrufen oder Dir gar per list comprehension eine Ergebnisstruktur zusammenbauen.

Und was Du für ein Problem hast, haben wir bisher immer noch bloß *implizit* herausgefunden :-P

(Das Parsen war ja offenbar gar kein Problem... :roll: )
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hindert dich daran, den Tag direkt herauszusuchen?

Code: Alles auswählen

def get_file_name(filename):
    main = ET.parse(filename)
    return main.findtext("images/image/file_name")
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Vielen Dank für eure Tipps und Hinweise!
Ich habe die Pfadnamen nun alle in einer Liste.
Beim Durchgehen habe ich aber noch ein Durcheinander. Ich möchte das erste File in "xml_d" nehmen und schauen, zu welem File es in "xml_f" passt. Falls sich die Texte entsprechen, sollen die beiden Pfadnamen ausgegeben werden. Wie mache ich das am besten?

(Momentan habe ich folgendes:

Code: Alles auswählen

for el in files:
    s = el.replace("[", "").replace("]", "").replace("'", "").replace('"', '').replace(",", "")
    try:
        if s[40:48] == "01/xml_d":
            de = get_file_name(s)
	    for ele in files:
		t = ele.replace("[", "").replace("]", "").replace("'", "").replace('"', '').replace(",", "")
		if t[40:48] == "01/xml_f":
		    fr = get_file_name(t)
		    if de == fr:
		        print s + "\t" + t
    except:
	pass
)
BlackJack

@MarcelF6: Was sind denn das für furchtbare Namen, die sind ja absolut nichtssagend. Und wie kommen die Elemente von `files` zustande? Wie sieht denn so ein Element aus?

Warum ignorierst Du da so grosszügig *alle* Ausnahmen?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich würde sagen, vergiss erst mal den Code und zeige uns auch keinen mehr. Zeige uns mal ein Beispiel von XML-Dateien und beschreibe, was Du mit diesen tun willst. Ansonsten kapieren wir hier immer weniger glaube ich...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hat alles geklappt, vielen Dank für die Inputs!

Eine Frage habe ich aber noch. Wenn ich ein xml der folgenden Form habe:

Code: Alles auswählen

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
</data>
Wie kann ich das File so einlesen, dass ich den gesamten Inhalt von 'data' habe?
Also konkret: Wieso erhalte ich bei folgendem Code ein leerer String und nicht den gesamten Inhalt?

Code: Alles auswählen

mainXml = ET.parse(xml_file)
	root = mainXml.getroot()
	print root.text
BlackJack

@MarcelF6: Weil das <data>-Element keinen Text enthält. Es enthält weitere Elemente.
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Ok, dann muss ich also alle Elemente hinzufügen?
Ist es nicht möglich, den gesamten Inhalt in data zu "lesen"?
Ich möchte sowas machen, bekomme aber eine Fehlermeldung.

Code: Alles auswählen

mainXml = ET.parse(xml_file)
	root = mainXml.find("data")
	root.append(self._findAlignment(os.path.basename(listOfPaths[0]))) # 'NoneType' object has no attribute 'append' 
        
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MarcelF6: Dir ist schon klar, was die Fehlermeldung bedeutet? »find« sucht unterhalb des Root-Knotens nach "data" was es natürlich nicht gibt, weil "data" der Root-Knoten ist. Den gesamten Text kann man mit »itertext« durchgehen, ich kann mir aber bei Deinen Daten keine sinnvolle Verwendung dafür ausdenken. Was willst Du wirklich tun?
Antworten