Datenbank und XML 12 Datenbank und XML Die Strategie von XML ist klar. einheitliches Java-Anwendungsprogramm einheitliche XML-Darstellung DB 1 DB 2 unterschiedliche Speicherung in verschiedenen Datenbanksystemen Das heisst, es gibt ein einheitliches Format zum Datenaustausch und es gibt ein einheitliches Format für Anwendungsprogramme Die Vorteile liegen auf der Hand: Während SQL (nur) eine Sprache ist für einheitliche Bearbeitungskommandos, ist XML eine Sprache zur einheitlichen Datendarstellung. Die Bezeichner, d.h. die Schemabeschreibungen, sind datennah dargestellt. Die Baumstruktur ermöglicht einen effektiven Zugriff, der letzten Endes endlich und vollständig ist. Evtl. ist er langsam. Nötig wäre noch: noch eine Leistungsunterstützung. Ein XML-Dokument enthält: eine optionale erste Zeile mit der Version von XML ein optionales Schema (DTD) ein Wurzelelement (das alle anderen Elemente enthält) SQL-Tabelle als XML-Ausdruck SQL-select und Ergebnistabelle select * from kunde kundenname pin kontostand ---------------------------------------------------------Meier 123 396.00 Müller 321 8000.00 Schulze 435 -223.00 select * from kunde for xml auto, elements, root (‚kunden’) <kunden> <row> <kundenname>Meier </kundenname> <pin>123</pin> <kontostand>396.00</kontostand> </row> <row> <kundenname>Mueller </kundenname> <pin>321</pin> <kontostand>8000.13</kontostand> </row> <row> <kundenname>Schulze </kundenname> <pin>435</pin> <kontostand>-223.27</kontostand> </row> </kunden> XML-Ausdruck als Baum kunden kunde kunde kundenname pin kontostand kundenname pin Meier 123 396.00 Müller 321 kunde kontostand kundenname pin 8000.00 Meier 435 Java-Anwendungsprogramme SAX-Programm: Konten < 0 markieren Dies kann in einem einzigen Durchlauf bearbeitet werden. Also ist SAX geeignet. import java.io.*; import java.sql.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; public class kontokleinernull extends DefaultHandler { static private Writer out; public void characters(char buf[], int offset, int len) throws SAXException { String s = new String (buf, offset, len); if (s.charAt(0) == '-') System.out.println(s+"Kontostand kleiner null"); else System.out.println(s); System.out.println(); } public static void main(String[] args) throws Exception { // hier fängt SQL an Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection("jdbc:odbc:sqlserverdb", "", ""); Statement s = c.createStatement(); String q = "select * from kunde2 for xml auto, elements, root('kunden')"; ResultSet rs = s.executeQuery(q); rs.next(); // hier fängt XML an -223.00 kontostand DefaultHandler handler = new kontokleinernull(); SAXParserFactory factory = SAXParserFactory.newInstance(); out = new OutputStreamWriter(System.out, "UTF8"); SAXParser saxParser = factory.newSAXParser(); saxParser.parse(new InputSource(new StringReader(rs.getString(1))),handler); } } Meier 12345 -396.00Kontostand kleiner null Müller 54321 8000.13 Schulze 54387 -223.27Kontostand kleiner null DOM-Programm: Konten < Kontendurchschnitt markieren Dazu muss in einem ersten Durchlauf der Kontendurchschnitt festgestellt werden. Dann können in einem zweiten Durchlauf die einzelnen Konten damit verglichen werden. Also ist DOM nötig. import com.sun.org.apache.xml.internal.serialize.*; import java.io.*; import java.sql.*; import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.*; public class kontokleinerdurchschnitt { static private Writer out; public static void serialize(Document doc, Writer writer) throws IOException { NodeList tagliste=doc.getElementsByTagName("kontostand"); int anz=tagliste.getLength(); System.out.println("Anzahl: "+anz); Node das_tag; int a; float durchschnitt, betrag, summe=0; String Name_des_Tags, inhalt; for (a=0;a<anz;a++) { das_tag=tagliste.item(a); Name_des_Tags=das_tag.getNodeName(); inhalt=das_tag.getFirstChild().getNodeValue(); summe = summe + Float.parseFloat(inhalt); }; durchschnitt = summe/anz; System.out.print("Durchschnitt: "); System.out.println(durchschnitt); for (a=0;a<anz;a++) { das_tag=tagliste.item(a); Name_des_Tags=das_tag.getNodeName(); inhalt=das_tag.getFirstChild().getNodeValue(); betrag = Float.parseFloat(inhalt); if (betrag <= durchschnitt) System.out.println("Tagname: "+Name_des_Tags+" Inhalt: "+inhalt+" = kleiner als Durchschnitt"); else System.out.println("Tagname: "+Name_des_Tags+" Inhalt: "+inhalt+" = grösser als Durchschnitt"); }; } public static void main(String argv[]) { kontokleinerdurchschnitt kd = new kontokleinerdurchschnitt(); try { // hier fängt SQL an Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection("jdbc:odbc:sqlserverdb", "", ""); Statement s = c.createStatement(); String q = "select * from kunde2 for xml auto, elements, root('kunden')"; ResultSet rs = s.executeQuery(q); rs.next(); // hier DB-Wert in einen File schreiben FileWriter content = new FileWriter("zzz.xml",true); content.write ("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"+rs.getString(1)); content.close(); // hier fängt XML an DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("zzz.xml")); serialize(doc, out); } catch(Exception ex){} } } <?xml version="1.0" encoding="ISO-8859-1"?> <kunden> <kunde2> <kundenname>Meier </kundenname> <pin>12345</pin> <kontostand>-396.00</kontostand> </kunde2> <kunde2> <kundenname>Müller </kundenname> <pin>54321</pin> <kontostand>8000.13</kontostand> </kunde2> <kunde2> <kundenname>Schulze </kundenname> <pin>54387</pin> <kontostand>-223.27</kontostand> </kunde2> </kunden> Anzahl: 3 Durchschnitt: 2460.2866 Tagname: kontostand Inhalt: -396.00 = kleiner als Durchschnitt Tagname: kontostand Inhalt: 8000.13 = grösser als Durchschnitt Tagname: kontostand Inhalt: -223.27 = kleiner als Durchschnitt TFH Berlin/Steyer