Redundante Zeitinformationen aus XML-Datei löschen

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
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Gerne möchte ich eine XML-Datei so bereinigen, dass doppelte Einträge gelöscht werden. Etwas Code habe ich schon geschrieben. Ich bräuchte noch Hinweise, wie man ein XML-Element löscht.

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
Created on Wed Jan 16 16:02:50 2019

@author: Admin
"""

import xml.etree.ElementTree as ET

def delete_equal_elements():
    """
    deletes redundant time information in GPX(XML)-file
    """
    tree = ET.parse('XML_files/Myway_B.xml')
    root = tree.getroot()
    
    timeList = []

    for child in root:
        for e1 in child:
            for e2 in e1:
                for e3 in e2:
                    eleTime = str(e3.text)
                    # print(time)
                    if eleTime[10:] != '':
                        timeList.append(eleTime[10:])
                    
    countEqualTimes = 0

    for i in range(0, len(timeList)-1):
        if timeList[i] == timeList[i+1]:
            countEqualTimes += 1
            root.remove # !!!!!!! what must be in this row? !!!!!!!
        
    print(countEqualTimes)
    
if __name__ == "__main__":
    delete_equal_elements()
Viele liebe Grüße, Strawk
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das sieht mir nicht besonders robust aus weil es nur nach der Struktur geht und die Tags komplett ignoriert. Das schöne an XML ist ja, dass man anderes XML darin einbetten kann. Wenn Du so eine Datei hast, dann kann das ganz böse auf die Nase fallen.

Die einzelnen Elemente `e1`, `e2`, und `e3` zu nennen, hilft nicht wirklich beim verstehen des Codes.

Wie `Element.remove()` funktioniert steht in der Dokumentation. Damit entfernst Du Elemente die direkte Kinder des Elements sind auf dem das aufgerufen wird. `root` wäre hier also falsch. Du wirst nur mit einer Liste der Zeiten nicht auskommen. Wobei bei den Zeiten die Frage ist ob die Zeichenkettenoperation da ausreicht und mit allen gültigen Zeitstempeln funktioniert.

Ich würde da ja die Kindelemente alle als Liste abfragen, dann die Liste filtern, und die im Elternelement durch die gefilterte Liste ersetzen. `Element`-Objekte unterstützen soweit ich das sehe Indexzuweisungen inklusive ”slicing”.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Zum Code: e3.text ist bereits ein String, das nochmal umzuwandeln ist unnötig. Die Abfrage »eleTime[10:] != ''« ist ziemlich kryptisch, klarer ausgedrückt »len(eleTime) > 10«.
Zu entscheiden, ob es sich um einen Timestamp handelt, anhand der Länge festzumachen ist aber sehr fragil. In GPS-Dateien sind Zeiten in einem <time>-Tag.
Mit lxml kann man dann per xPath relativ leicht alle <time>-Tags finden, diese zu filtern und den Parent aus dem Großvater löschen.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Versuche gerade, mit lxml zu arbeiten. Folgender Code:

Code: Alles auswählen

from lxml import etree 

def delete_equal_elements():
    root = etree.XML("data/Myway_D.xml")

    find_text = etree.XPath("//text()")
    text = find_text(root)[0]
    print(text)

    print(text.getparent().text)

    find_text = etree.XPath("//text()", smart_strings=False)
    text = find_text(root)[0]
    print(text)
    
    hasattr(text, 'getparent')
        
if __name__ == "__main__":
    delete_equal_elements()
macht folgende Fehlermeldung:
XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1
Die XML-Datei ist aber okay.

Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Wie sieht die XML-Datei denn aus? Du *glaubst* dass sie korrekt formatiert ist, oder du hast es geprüft?
When we say computer, we mean the electronic computer.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Ja, ich habe es geprüft.

LG Strawk
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Was ist denn die Ausgabe von

Code: Alles auswählen

with open("data/Myway_D.xml") as f:
    print(repr(f.read().split("\n")[0]))
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo sparrow!

Dabei kommt heraus:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das kommt dabei garantiert nicht raus. So sieht das hier aus

Code: Alles auswählen

'\'<?xml version="1.0" encoding="UTF-8"?>\''
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: Du kannst nicht einfach irgendwelche Funktionen benutzen, deren Dokumentation nicht lesen und trotzdem hoffen, dass sie das richtige machen. Der String "data/Myway_D.xml" ist kein gültiges XML. Wenn Du den Inhalt von Dateien parsen willst, benutze >etree.parse<.

Der XPath-Ausdruck ist viel zu allgemein. Du suchst nur <time>-Tags.
Antworten