Seiten

Donnerstag, 10. Mai 2012

Informationen aus (sehr) großen XML-Dateien auslesen

1. Vorgeschichte

Seit längerem habe ich nach einer Möglichkeit gesucht, Informationen aus mehreren XML-Dateien auszulesen, ohne jede einzelne Datei seperat bearbeiten zu müssen.
Der Datenbestand besteht aus 1922 einzelnen XML-Dateien die knapp 850 MByte auf die "Waage" bringen. Die Struktur der Dateien ist immer gleich.

Der erster Versuch war die Daten mittels Excel auszuwerten. jedoch stieß Excel - oder mein Arbeitsrechner - an seine grenzen, sodass alleine das Importieren der Dateien mehrere Stunden dauerte und ein anschließendes Arbeiten unmöglich war.
Eine weitere Option sah ich in Access. Jede einzelne XML-Datei lies sich importieren. Blieb die Anzahl bei einer Datei, konnte man auch genaue Abfragen formulieren. Importierte ich jedoch mehr als nur eine Datei, konnten keine gescheiten Abfragen mehr formuliert werden, das keine Kadinalitäten übernommen oder erstellt worden sind. Die folge war, dass die Daten aus ihrem Zusammenhang gerissen worden sind.
Sofern der Leser hierzu eine Möglichkeit kennt, mehrere XML-Dateien in eine Access Datenbank zu importieren, die gleichzeitig Kardinalitäten auf Grund der XML-Struktur erstellt, würde es mich freuen wenn die oder derjenige sich melden würde.
Schließlich stieß ich auf den Begriff der "XML-Datenbanken" und fand dazu eine OpenSource Datenbank mit dem Namen BaseX.

2. Der Start

Nach dem Start des Java Programms erstellt man sich eine neue Datenbank (Datenbank -> neu), gibt ihr einen Namen und legt die zu importierende XML-Datei oder den Ordner fest, aus dem die Dateien importiert werden sollen. Nun muss nicht mehr jede Datei einzeln importiert werden.
Nun werden die die Datensätze eingelesen.


3. Speicherproblem

Es zeigte sich, dass die zu verarbeitende Datenmenge doch zu groß war. Kurz nach Beginn des Importvorganges meldete sich BaseX mit einer Fehlermeldung. Der zur Verfügung gestellte Speicher sei zu klein bzw. schon voll. Als Hinweis wurde u.a. das setzen einer "Java-Flag" vorgeschlagen.
-Xms<Size> -Xmx<Size>    (Quelle)
Als Größe für den zur Verfügung gestellten Speichern entschloss ich mich für 1 GB ~ 1024MB.
Um das Java-Programm mit dieser vorrübergehenden Einstellung zu starten, muss es unter Windows über die CMD gestartet werden. Der Befehl sieht wie folgt aus:
C:\> "C:\Program Files (x86)\Java\jre6\bin\java.exe" -Xms1024M -Xmx1024M -jar C:\...\BaseX702\basex\BaseX.jar

Das modifizierte BaseX fügt nun die XML-Dateien problemlos ein. Die gesmate Datenmenge wurde in einer knappen Minute importiert.


4. Die Abfrage

Um nun an die gewünschten Daten zu kommen, muss eine Abfrage mittels XQuery formuliert werden. Im Netz findet man viele Wikis, Forenbeiträge sowie Tut's zu diesem Thema. Am Ende habe ich einige Links hinzugefügt, die mir sehr weitergeholfen haben.

Meine formulierte Abfrage sieht wie folgt aus:
<Bericht>
{
for $Bericht in //Qualitaetsbericht
return
 <a>
  {
  for $Fallzahl in ($Bericht//Hauptdiagnose)
  where $Fallzahl[starts-with(ICD_10,"HIER_STEHT_DER_ICD10_CODE")]
  return
   if ($Fallzahl/Fallzahl>0)
   then <Ausgabe>
    
       {<Jahr>2010</Jahr>}
       {$Bericht/Krankenhaus_Name}
       {$Bericht/Kontaktdaten/Hausanschrift/Postleitzahl}
       {$Bericht/Kontaktdaten/Hausanschrift/Ort}
   
    
       {$Fallzahl/ICD_10}
       {$Fallzahl/Fallzahl}
       {<anonym></anonym>}     
    
     </Ausgabe>
   else <Ausgabe>
    
       {<Jahr>2010</Jahr>}
       {$Bericht/Krankenhaus_Name}
       {$Bericht/Kontaktdaten/Hausanschrift/Postleitzahl}
       {$Bericht/Kontaktdaten/Hausanschrift/Ort}
   
    
       {$Fallzahl/ICD_10}
       <Fallzahl></Fallzahl>
       {<anonym>1 bis 4</anonym>}
    
     </Ausgabe>
  }
 </a>
}
</Bericht>

Erläuterung:
In die Varibale $Bericht wird ein Zeiger auf die Nodes "Qualitaetsberichte" gelegt. Dieser Node exestiert pro XML-Datei einmal. Somit durchläuft die erste For-Schleife alle XML-Dateien.
Im ersten Durchlauf gibt der nächste befehl nun den Namen des Krankenhauses aus, der für diesen einen Qualitätsbericht hinterlegt ist.
Im nächsten Schritt startet eine neue For-Schleife. Diese zweite Schleife durchsucht nun alle Hauptdiagnosen dieses einen Qualitätsberichtes nach der ICD10 codierten Diagnose und Untergruppen davon. Sollten solche Hauptdiagnosen gefunden weren, werden die Anzahl der Fälle bzw. die auf grund von Datenschutz nicht angegebenen Fallzahlen ausgegeben.

Hier noch eine Abfrage für OPS-Codes:
<Bericht>
{
for $Bericht in //Qualitaetsbericht
where $Bericht/Krankenhaus_Name='*****'
return
 <a>
  {
  for $Fallzahl in ($Bericht//Prozeduren/Verpflichtend/Prozedur)
  where $Fallzahl[starts-with(OPS_301,"HIER_STEHT_DER_OPS301_CODE")]
  return
   if ($Fallzahl/Fallzahl>0)
   then <Ausgabe>
    
       {<Jahr>2008</Jahr>}
       {$Bericht/Krankenhaus_Name}
       {$Bericht/Kontaktdaten/Hausanschrift/Postleitzahl}
       {$Bericht/Kontaktdaten/Hausanschrift/Ort}
   
    
       {$Fallzahl/OPS_301}
       {$Fallzahl/Fallzahl}
       <anonym></anonym>     
    
     </Ausgabe>
   else <Ausgabe>
    
       {<Jahr>2008</Jahr>}
       {$Bericht/Krankenhaus_Name}
       {$Bericht/Kontaktdaten/Hausanschrift/Postleitzahl}
       {$Bericht/Kontaktdaten/Hausanschrift/Ort}
   
    
       {$Fallzahl/OPS_301}
       <Fallzahl></Fallzahl>
       <anonym>1 bis 4</anonym>
     </Ausgabe>
  }
 </a>
}
</Bericht>
Leider habe ich es bisher noch nicht geschafft die einzelnen Fallzahlen zu summieren und nur jene Krankenhäuser anzuzeigen, die auch diese Diagnosen hatten.
Schließlich bin ich so verblieben dass ich mir die Zahlen zu den relevanten ICD_10- und OPS_301-Codes über XQuery ausgeben lassen und die exportierte XML-Datei in Acceess auswerte.

Zur Information: Die XQuery-Abfrage sollte dazu dienen, Krankenhäuser ausfindig zu machen, die eine große Fallzahl bestimmten Codierungen gemeldet hatten.


5. Nützliche Links

Keine Kommentare:

Kommentar veröffentlichen