Seite 1 von 1

XML Datei analysieren

Verfasst: Mittwoch 16. Oktober 2024, 21:14
von guhamail
Hallo,

gegeben sei die folgende XML Datei:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>

<DataSet>
	<Version>2024</Version>
	<DataSupplier>
		<Name>FirmaXY</Name>
		<Location>LocationXY</Location>
		<Comment>Stand_30.09.2023</Comment>
	</DataSupplier>
	<Media>
		<Name>Datenträger</Name>
		<Table>
		  <URL>programminfo.csv</URL>
		  <Name>Programminfo</Name>
		  <Description>Informationen zum Softwareprogramm</Description>
		  <DecimalSymbol>,</DecimalSymbol>
		  <DigitGroupingSymbol>.</DigitGroupingSymbol>
		  <VariableLength>
		    <VariableColumn>
			   <Name>Softwarehersteller</Name>
			   <Description>Softwarehersteller</Description>
			   <AlphaNumeric/>
			   <MaxLength>60</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		       <Name>Softwarebezeichnung</Name>
		       <Description>Name der Software</Description>
		       <AlphaNumeric/>
		       <MaxLength>60</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		       <Name>Version</Name>
		       <Description>Versionsnummer</Description>
		       <AlphaNumeric/>
		       <MaxLength>60</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		       <Name>Branche</Name>
		       <Description>Anwendungsgebiet</Description>
		       <AlphaNumeric/>
		       <MaxLength>60</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		       <Name>Anschrift</Name>
		       <Description>Anschrift Hersteller</Description>
		       <AlphaNumeric/>
		       <MaxLength>60</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		       <Name>Ort</Name>
		       <Description>Ort Hersteller</Description>
		       <AlphaNumeric/>
		       <MaxLength>60</MaxLength>
		    </VariableColumn>
		  </VariableLength>
		</Table>
		<Table>
			<URL>stammdaten.csv</URL>
			<Name>Kundenstammdaten</Name>
			<Description>Angaben zum Kunde</Description>
			<DecimalSymbol>,</DecimalSymbol>
			<DigitGroupingSymbol>.</DigitGroupingSymbol>
			<VariableLength>
			  <VariableColumn>
				   <Name>KU_NR</Name>
				   <Description>Kundennummer</Description>
                   		   <AlphaNumeric/>
				   <MaxLength>14</MaxLength>
				</VariableColumn>
				<VariableColumn>
				   <Name>KU_Name</Name>
				   <Description>Name des Kunden</Description>
                  		  <AlphaNumeric/>
				   <MaxLength>40</MaxLength>
				</VariableColumn>
				<VariableColumn>
				  <Name>KU_Strasse_Nr</Name>
				  <Description>Straße und Hausnummer des Kunden</Description>
				  <AlphaNumeric/>
				  <MaxLength>40</MaxLength>
				</VariableColumn>
				<VariableColumn>
				  <Name>KU_Plz</Name>
				  <Description>PLZ des Kunden</Description>
				  <AlphaNumeric/>
				  <MaxLength>40</MaxLength>
				</VariableColumn>
			</VariableLength>
		</Table>
		<Table>
		  <URL>lieferantenstammdaten.csv</URL>
		  <Name>Lieferantenstammdaten</Name>
		  <Description>Angaben zum Lieferanten</Description>
		  <DecimalSymbol>,</DecimalSymbol>
		  <DigitGroupingSymbol>.</DigitGroupingSymbol>
		  <VariableLength> 
		    <VariableColumn>
		      <Name>Li_Jahr</Name>
		      <Description>Lieferjahr</Description>
		      <Numeric/>
		    </VariableColumn>
		    <VariableColumn>
		      <Name>Li_Mon</Name>
		      <Description>Liefermonat</Description>
		      <Numeric/>
		    </VariableColumn>
		    <VariableColumn>
		      <Name>Li_Zahl</Name>
		      <Description>Lieferzähler</Description>
		      <Numeric/>
		    </VariableColumn>
		    <VariableColumn>
		      <Name>Li_Nr</Name>
		      <Description>Liefernummer</Description>
		      <AlphaNumeric/>
		      <MaxLength>40</MaxLength>
		    </VariableColumn>
		    <VariableColumn>
		      <Name>ID_Nr</Name>
		      <Description>Identifikationsnummer</Description>
		      <AlphaNumeric/>
		      <MaxLength>11</MaxLength>
		    </VariableColumn>
		  </VariableLength>
		</Table>
	...
	</Media>
</DataSet>

Ich möchte den Inhalt der XML analysieren und mit einer Standardvorgabe vergleichen. Speziell interessieren mich erstmal die Tags <name> , <MaxLength>, <numeric> und <AlphaNumeic>.

Als Schwierigkeit kommt hinzu, dass auf dem System, wo das Skript laufen soll, das Modul pandas nur in der Version 0.20 verfügbar ist. Die Methode read_xml() steht also nicht zur Verfügung. Die installation weiterer Module ist auf dem System nicht möglich.

Ich stehe an dem Punkt, dass ich die XML in eine Liste eingelesen habe.

Code: Alles auswählen

datei = open("index.xml").readlines()
datei = [l.strip() for l in datei]
Wie extrahiere ich jetzt alle <table> Abschnitte aus der Liste?

Re: XML Datei analysieren

Verfasst: Mittwoch 16. Oktober 2024, 21:46
von __blackjack__
@guhamail: XML ist kein unstrukturierter Text, da sind Zeilen keine sinnvolle Einheit das zu verarbeiten. Dafür nimmt man einen XML-Parser. Beispielsweise `xml.etree.ElementTree` aus der Standardbibliothek.

Re: XML Datei analysieren

Verfasst: Freitag 18. Oktober 2024, 14:33
von __blackjack__
Mal als Ansatz:

Code: Alles auswählen

#!/usr/bin/env python3
from enum import Enum
from xml.etree import ElementTree

from attrs import field, frozen


class ColumnType(Enum):
    ALPHANUMERIC = "AlphaNumeric"
    NUMERIC = "Numeric"


@frozen
class Column:
    name = field()
    type = field()
    max_length = field(default=None)

    @classmethod
    def from_xml_element(cls, element):
        name = element.findtext("Name")
        for column_type in ColumnType:
            if element.find(column_type.value) is not None:
                break
        else:
            raise ValueError(
                f"{element.tag} element with name {name!r} that has no"
                f" ColumnType"
            )
        max_length_text = element.findtext("MaxLength")
        max_length = int(max_length_text) if max_length_text else None
        return cls(name, column_type, max_length)


@frozen
class Table:
    url = field()
    columns = field(factory=list)

    @classmethod
    def from_xml_element(cls, element):
        return cls(
            element.findtext("URL"),
            list(
                map(
                    Column.from_xml_element,
                    element.findall("VariableLength/VariableColumn"),
                )
            ),
        )


def parse_tables(filename):
    return map(
        Table.from_xml_element,
        ElementTree.parse(filename).findall("Media/Table"),
    )


def main():
    for table in parse_tables("test.xml"):
        print(table.url)
        for column in table.columns:
            print(" ", column)


if __name__ == "__main__":
    main()
Ausgabe für die Testdaten aus dem ersten Beitrag:

Code: Alles auswählen

programminfo.csv
  Column(name='Softwarehersteller', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
  Column(name='Softwarebezeichnung', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
  Column(name='Version', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
  Column(name='Branche', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
  Column(name='Anschrift', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
  Column(name='Ort', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=60)
stammdaten.csv
  Column(name='KU_NR', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=14)
  Column(name='KU_Name', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=40)
  Column(name='KU_Strasse_Nr', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=40)
  Column(name='KU_Plz', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=40)
lieferantenstammdaten.csv
  Column(name='Li_Jahr', type=<ColumnType.NUMERIC: 'Numeric'>, max_length=None)
  Column(name='Li_Mon', type=<ColumnType.NUMERIC: 'Numeric'>, max_length=None)
  Column(name='Li_Zahl', type=<ColumnType.NUMERIC: 'Numeric'>, max_length=None)
  Column(name='Li_Nr', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=40)
  Column(name='ID_Nr', type=<ColumnType.ALPHANUMERIC: 'AlphaNumeric'>, max_length=11)