Know How - XML
Hier einige Worte zu XML oder wie ich arbeite.Links
- xml2sql-v und eine kleine FAQ dazu.
Dieses Tool habe ich geschrieben um beliebige korrekte XML-Dateien in beliebige SQL-Datenbanken pumpen zu können, ohne dass vorher das Schema der XML-Datei bekannt sein muss. Man kann danach die XML-Inhalte mit SQL weiterverarbeiten. Es ist also ein "generischer XML-Loader" der dem XML-File keinerlei Strukturen aufzwingt.
Kommentare
Heise
- Im Heise-Forum habe ich dazu etwas gepostet:
Rein per SQL, raus per XML. XML in der DB brauchte ich nie
MySQL hat die Möglichkeit, den Query als XML zu dumpen. Das nutze ich gerne um das in andere Tools zu pipen. Das hat natürlich wenig mit XML-Fähigkeit der Datenbank zu tun, aber ich vermisse solch ein natives Feature immer bei anderen Datenbanken (hm, da fällt mir ein, ich könnte dieses Wochenende sq mal XML beibringen:www.scylla-charybdis.com/tool.php?tool=sq
SQ ist ein Query-Frontend für SQLite3 das für die Nutzung via Bash optimiert ist). XML hat den entscheidenden Vorteil dass es die Ergebnise (Spalteninhalte) ohne irgendwelche Kopfstände in andere Scripte transportieren kann. Das funktioniert mit anderen Methoden nicht so leicht, da man immer Schwierigkeiten mit Freitexten hat die in so Datensätzen vorkommen können. Die XML-Fähigkeit von MySQL ist allerdings extrem rudimentär. Es reicht mir jedoch. Und as Gute ist, dass langsam so gut wie jede Datenbank XML als Query-Ergebnis liefern kann. Rein geht es per SQL, da gibt es im Wesentlichen nur 2 Dialekte, "echtes" SQL (Hochkommata müssen verdoppelt werden um sie zu dequoten) und das MySQL-Derivat (per Backslash, da recht ein kurzes SED/AWK um das aus echtem SQL zu bauen). Rauswärts geht es eben mit XML. Die Schnittstelle ist also ein beliebiges Commandline-basiertes Query-Tool das SQL ausführen kann und mit den richtigen Schaltern XML erzeugt. Wenn letzteres nicht geht kann man noch ein AWK basteln und muss eben hoffen, dass der Spaltenseparator nicht vorkommt. Geht das nicht muss man den mühsamen Weg über einen Export beschreiten. Eine direkte XML-Fähigkeit des Query-Tools ist da echt von Vorteil. Der Weg den ich beschreite ist also oft: Rein per SQL.
Raus per XML. Wenn ich eine XML-Datei in eine Datenbank pumpen muss, dafür habe ich vor Jahren schon xml2sql-v geschrieben:
www.scylla-charybdis.com/tools.html#xml2sql-v
(Das Tool hat zwar einen Bug im Makefile, aber der ist so lächerlich, dass den jeder schon selber finden sollte.) Richtig, das Tool ist uralt, aber es gab noch keine besondere Notwendigkeit, es zu ändern weil es genau das tut was es soll: Den Inhalt eines beliebigen (korrekten) XML per SQL in eine Datenbank zu pumpen, so dass man die XML-Strukturen anschließend mit SQL herausfinden kann (naja, braucht meistens eine dieser üblen Pivot-Transformationen eg) und die Inhalte somit aus den Transfertabellen herausfischen kann. (Hey, ich sage nicht, dass das für jeden einfach ist, aber der Vorteil ist, es funktioniert ohne Mucken, da kann also der letzte Mist ankommen aber so lange es XML ist funktioniert es). Der XML-Parser meiner Wahl ist übrigens EXPAT. Das Teil ist ziemlich leicht benutzbar, kenn zwei Modi die eigentlich immer ausreichen (Iterativ und Callback) und ist vor allem eine korrekter XML-Parser (also dass der beim ersten falschen Zeichen die Grätsche macht ist kein Feature sondern eine Grundvoraussetzung). Abgesehen davon ist er echt gutmütig. xml2sql-v ist solch ein (übrigens ziemlich einfach gestricktes) EXPAT-basiertes Programm - deshalb muss ich es auch nicht ändern, die eigentliche Arbeit erledigt EXPAT seit Jahren. Wer sich jetzt fragt, was das mit XML-Fähigkeit einer Datenbank zu tun hat: Wenn ich mich so umsehe wie die Leute so ihre XML-Dateien bauen, kommt einem gerne das kalte Grausen. Ich habe schon folgendes erlebt (ich bin übrigens kein XML-Gott sondern nur ein XML-Wurm. Sprich, mit Schemata oder XSLT habe ich nie was gemacht):
- Entitätenchaos: Die Entitäten werden falsch mitgeliefert, in einer
UTF-8-Datei kommen direkte Latin-1-Zeichen vor. Entsprechender Fixer
ist in xml2sql-v deshalb vorhanden.
- Landessprachen: Statt UTF-8 wird eine der unbekannteren
Landessprachen verwendet, was Expat sofort maulen lässt. Expat um
dieverse Zeichensätze zu erweitern ist schwierig, weshalb man sich
auf UTF-8 bzw. Latin-1 beschränken sollte. UTF-8 unterstützt auch
Asiatisch. Wenn es also nicht ISO-8859-1 ist dann bitte UTF-8
nehmen!
- Leerelemente: Ein Schema ist eh für die Katz (das zu parsen macht
Programme zu kompliziert - man will ja nur an die Daten, das Schema
hilft da eher wenig), also fehlt das grundsätzlich oder ändert sich
schneller als die Unterhose des Programmierers der den Mist
verbrochen hat. Warum dann aber einige Leute auf die Idee kommen,
die Daten in die Element-Attribute statt in den Inhalt eines Elements
zu sperren und ausschließlich mit Leerelementen zu arbeiten entzieht
sich vollständig meinem Verständnis.
- Singulärelement: Aber das mit den Leerelementen (was vermutlich
aus einem rekursiven Strukturdump entspricht) ist noch genial zu
nennen gegen die Konsorten, die grundsätzlich nur ein Element kennen,
das dann wie wild verschachtelt wird, und dessen Typ über die
Attribute definiert wird!
- Verschärfter: Dann gibt es natürlich die Leute, die jede beliebige
Mischform erstellen, und das am besten noch wechselnd im selben XML
gerade wie es lustig ist, wobei natürlich jegliches Anfangs-End-Tag
vergessen wird, sprich, man hat bei N Datensätzen N Anfänge und N
Enden. Das habe ich auch schon Rekursiv erlebt, d. h. die XML-Datei
enthält ausschließlich öffnende TAGs bis die Daten alle gedumpt
wurden, und dann folgen auf einen Schlag alle schließenden TAGs,
"damit es korrrektes XML wird".
<?xml version="1.0" encoding="ISO-8859-1"?>
<query>
<row>
<vorname>Werner</vorname>
<nachname>Müller</nachname>
<money>100,00€</money>
</row>
<row>
..usw..
</row>
</query>
<?xml version="1.0" encoding="ISO-8859-1"?>
<query>
<row>
<vorname text="Werner" />
<nachname text="Müller" />
<money currency="100,00€" />
</row>
<row>
..usw..
</row>
</query>
<money type="Currency">100,00€</money>
<?xml version="1.0" encoding="ISO-8859-1"?>
<data name="row1">
<data name="Vorname" text="Werner" />
<data name="Nachname" text="Müller" />
<data name="Money" currency="100,00€" />
</data>
<data name="row2">
..usw..
</data>
<?xml version="1.0" encoding="ISO-8859-1"?>
<data row=1 name="Vorname" text="Werner">
<data row=1 name="Nachname" text="Müller">
<data row=1 name="Money" currency="100,00€">
<data row=2 name="Vorname" text="Hans">
<data row=2 name="Nachname" text="Meier">
<data row=2 name="Money" currency="20,00€">
..usw..
</data></data></data></data></data></data>
<data ... />
select '</data>' from table"