Tipps & Tricks - XML per Datentransfer einlesen
Da XML-Dateien sehr unterschiedliche Strukturen haben können, kommt man nicht
umhin, für jeden Import einer XML-Datei ein individuelles Import-Skript
zu schreiben. Intrexx bietet dafür die Möglichkeit, bei einem Datentransfer
ein entsprechendes Groovy-Skript als Datenquelle zu verwenden.
XML-Struktur analysieren
Für dieses Beispiel wird ein
Applikationsexport
mit Daten vorgenommen. Ändern Sie die Endung
lax der
Exportdatei um in
zip, um die Datei anschließend zu
entpacken. Intrexx speichert Daten im Applikations-Export als XML. Das Verzeichnis, in dem Sie
die entsprechende Daten-Datei in der entpackten Exportdatei finden können, wird von Intrexx
wie folgt erzeugt:
Name-der-Applikation\GUID-der-Applikation\data
In diesem Ordner werden die XML-Dateien, die die Daten enthalten, nach den
entsprechenden Datengruppen, die in der Export-Applikation enthalten sind, benannt
- z.B.
XDATAGROUP00D1A218.data. Die Struktur der XML-Datei sieht
in etwa so aus:
<dump>
<schema>
…
</schema>
<data>
<r>
<c n="lid">1</c>
<c n="luserid">1</c>
<c n="luseridinsert">1</c>
<c n="dtinsert"> 2016-11-24T08:59:42.064Z</c>
<c n="dtedit"> 2016-11-24T08:59:42.064Z</c>
<c n="str_titel_6a585d30">Erster Eintrag</c>
</r>
…
</data>
</dump>
Für jeden Datensatz kommt ein weiteres <r>-Element dazu.
Groovy-Skript schreiben
Beim Erstellen des
Datentransfers muss die Datenquelle auf
Groovy-Skript geändert werden.
Klicken Sie
Weiter.
Intrexx generiert zu Beginn ein Dummy-Skript, das allgemein gehalten und
nicht speziell für XML-Daten gedacht ist. Dieses Skript muss nun noch abgeändert
werden. Öffnen Sie dazu den Intrexx-Editor, indem Sie hier auf den entsprechenden
Link klicken.
Zunächst muss der Klasse
DataSet eine
Methode
parseXML
hinzugefügt werden, die den Inhalt unabhängig vom eigentlichen Datentyp als Text
in einen Zwischenspeicher lädt. Diese muss beim Erstellen des DataSet in der
Methode
getDataSet auch zwingend aufgerufen werden,
bevor das erzeugte Objekt zurückgegeben wird. Anschließend wird die Methode
next angepasst, um die Werte aus dem Zwischenspeicher
in den tatsächlichen Datentyp zu konvertieren. In diesem Beispiel findet
man die korrekten Java-Datentypen in der XML-Datei selbst, dort werden
im Schema-Abschnitt die Datentypen der einzelnen Datenfelder mit angegeben.
Hier das komplette Groovy-Skript für die Quelle:
import de.uplanet.lucy.server.datatrans.IDataSet
import de.uplanet.lucy.server.datatrans.IDataObject
import de.uplanet.lucy.server.datatrans.table.DefaultDataRecord
import java.text.SimpleDateFormat
import java.util.TimeZone
void open(){}
void close(){}
/**
* Returns the data set, from which the data will be read when importing from this data source.
* @return data set
*/
IDataSet getDataSet()
{
def ds = new DataSet()
ds.parseXML()
return ds
}
/**
* This class is the data source specific data set implementation.
*/
class DataSet implements IDataSet
{
def sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
def fileContents = new File("C:\\XML_SOURCE_DATA.data").getText("UTF-8")
def content = new XmlParser().parseText(fileContents)
def xmlRows = content.data.r
def rows = []
def i = 0
void parseXML(){
for(xmlRow in xmlRows)
{
def row = [:]
def xmlColumns = xmlRow.c
for(xmlColumn in xmlColumns)
{
def strColumnName = xmlColumn."@n"
def strValue = xmlColumn.text()
row.put(strColumnName, strValue)
}
rows.add(row)
}
}
IDataObject next(){
if (i >= rows.size()) return null;
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
def l_record = new DefaultDataRecord(null, [
"lid":java.lang.Integer,
"luserid":java.lang.Integer,
"luseridinsert":java.lang.Integer,
"dtinsert":java.sql.Timestamp,
"dtedit":java.sql.Timestamp,
"str_titel":java.lang.String,
])
def row = rows[i]
l_record.setValue("lid", Integer.parseInt(row.get("lid")))
l_record.setValue("luserid", Integer.parseInt(row.get("luserid")))
l_record.setValue("luseridinsert", Integer.parseInt(row.get("luseridinsert")))
l_record.setValue("dtinsert", new java.sql.Timestamp(sdf.parse(row.get("dtinsert")).getTime()))
l_record.setValue("dtedit", new java.sql.Timestamp(sdf.parse(row.get("dtedit")).getTime()))
l_record.setValue("str_titel", row.get("str_titel"))
i++;
return l_record
}
void close(){}
}
|
Die XML-Datei wird bei dieser Methode zuerst komplett in
den Arbeitsspeicher geladen und anschließend verarbeitet.
Bei großen Dateien kann dies zu einem Speicherüberlauf führen,
weshalb in diesem Fall speziellere Methoden genutzt werden sollten.
|
Kopieren Sie das Beispiel-Skript und fügen Sie es im Editor ein.
Klicken Sie
Weiter.
Wählen Sie hier das Ziel für den Import aus und klicken Sie
Weiter.
Wählen Sie hier die Datengruppe aus, in die die Daten importiert werden sollen.
Klicken Sie
Weiter.
Zuletzt müssen die Daten noch transformiert werden. Dazu muss die Einstellung
Transformation verwenden, wenn unterstützt hier
gesetzt sein. Klicken Sie
Weiter.
Öffnen Sie den Intrexx-Editor.
Der Assistent beim Anlegen des Datentransfers hat das Feld für die Transformation bereits
entsprechend geändert, sodass hier jetzt auch ein Groovy-Skript hinterlegt werden kann.
Die Transformation ordnet Datenfelder aus der Quelle den Datenfeldern im Ziel zu. Werden beim Import eigene IDs
benötigt, so ist dies die Stelle, an der sie erzeugt und dem ID-Feld zugeordnet werden
können. Für dieses Beispiel wird dieses Vorgehen nicht benötigt. Die Quell- und
Zielfelder können hier ganz einfach entsprechend zugeordnet werden.
Hier das Groovy-Skript für die Transformation:
g_destination.setValue("lid", g_source.getValue("lid"))
g_destination.setValue("luserid", g_source.getValue("luserid"))
g_destination.setValue("luseridinsert", g_source.getValue("luseridinsert"))
g_destination.setValue("dtinsert", g_source.getValue("dtinsert"))
g_destination.setValue("dtedit", g_source.getValue("dtedit"))
g_destination.setValue("str_titel", g_source.getValue("str_titel"))
|
Bitte prüfen Sie die Groß-Kleinschreibung im Groovy-Skript, wenn
Daten nicht übernommen werden. Je nach Servertyp muss u.U. die
Groß-Kleinschreibung sowohl in der
Formulierung der Quelle als auch in der Transformation berücksichtigt werden.
|