Posts mit dem Label XML werden angezeigt. Alle Posts anzeigen
Posts mit dem Label XML werden angezeigt. Alle Posts anzeigen

sync4db

Bei der Entwicklung von cms4xml habe ich auf meinem PC natürlich eine Testumgebung aufgebaut; sprich: Testdatenbank eingerichtet usw. Und natürlich wird auch immer dort fleißig weiter entwickelt, so dass zwischen der Test- und der Realdatenbank beim Hoster naturgemäß Differenzen sind. Diese immer per phpMyAdmin manuell auszugleichen, ist ein Kreuz. Also was lag näher, als sich eine Datenbanksynchronisation zu überlegen.

Erster Gedanke: Eine Datenbankreplikation. Geht nur nicht, weils der Hoster nicht anbietet (naja, hab halt nur Space und keinen root-Server dort).

Zweiter Gedanke: Es wird wohl jemand so etwas anbieten, ist ja kein unübliches Problem. Hmm, leider nichts Rechtes gefunden, weil es muss ja auch beim Hoster installierbar sein, geht eigentlich nur, wenn es in PHP geschrieben ist.

Dritter Gedanke: Dann schreibst eine Client/Server-Geschichte, die mit sich selbst aushandelt, was zu tun ist. Am Besten überträgt sie die Daten per XML.

Vierter Gedanke: So was hatte wir doch schon mal ... beim Zugriff von Blog-Writer- Programmen. Da musste man doch für die Datenbankseite eine xmlrpc-Server implementieren ... Gab es da nicht was als PEAR Klasse? Genau!

Herausgekommen sind zwei PHP-Skripte für die Datenbanktabellen-Synchronisation. Das Prinzip: Das Client-Skript fragt beim Server-Skript nach, wie die md5-Hashes pro Tabellenzeile bei der remoten Datenbank sind und vergleicht sie mit den md5-Hashes der lokalen Datenbank. Bei Abweichungen wird der Inhalt nach Belieben (man kann sich die Richtung aussuchen) ausgetauscht.

Ein wenig Sicherheit ist mit Basic HTTP-Authentification auch eingebaut (SSL würde auch gehen), ein paar Datenbankadministrationsfunktionalitäten wurden dazu geschrieben wie Tabelle leeren, löschen, clonen, kopieren usw. und ein wenig Datensicherung und nützliche Protokolierung muss auch noch sein, wie veränderte Tabellenzeilen werden vorher in eine neue Tabelle kopiert, die abweichenden Tabellenzeilen werden in eine neue Tabelle geschrieben. Fertig ist sync4db, anzuschauen hier.

A new CMS is born: cms4xml

Da hab ich mich doch in den letzten Wochen mit der Entwicklung eines Web Content Management Systems herumgeschlagen. Warum? Weil ich mich mal wieder darüber geärgert habe, dass ich nicht auf die Schnelle was aus der Datenbank publizieren konnte, die Version von meinem alten im Einsatz befindelich CMS schon längst fällig war, wieder erneuert zu werden und und und. Schlimm sind immer die Anpassungen bei neuen Versionen, die ich in der Vergangenheit an dem eingesetzten CMSen vorgenommen hatte und die natürlich händisch Codezeile für Codezeile nachgearbeitet sein wollen, wenn wieder alles so aussehen soll wie mal zuvor. Ein #@*§$%*-Job!

Also habe ich mich mal hingesetzt und alles zusammengetragen, was ich schon immer wollte: XML, XSL, AJAX, PHP, CSS ...

... und was kleines, feines ist herausgekommen: cms4xml.

cms4xml ist ein kleines, einfaches Web Content Management System.

Es ist frei verfügbar. Es ist erweiterbar. Es nutzt Standards: XML, XSLT, CSS, JavaScript, SQL und die weitverbreitete Programmiersprache PHP, sowie die AJAX-Funktion: XMLHttpRequest() und die PEAR-Klassen: MDB2 und Query2XML. Im Grunde ist cms4xml AJAX pur.

cms4xml kann, muss aber nicht mit einer Datenbank zusammen betrieben werden.

cms4xml Stärke ist es, dass es jegliche Daten von SQL-Datenbanken verwenden oder XML-Daten anderer Programme integrieren kann.

Wer Lust hat, kann sich ja mal meine Web-Seite von cms4xml anschauen und probieren. Hier ist der Link: cms4xml

Ich würde mich freuen, wenn es gefällt.

Wie man XML mit XSL im JavaScript verbindet -> AJAX pur

Nachdem ich mich mit der Prototype-Lösung für XML abgemüht habe (siehe unten), ist meine Zufriedenheit immer noch nicht ganz da. Es wäre doch wirklich schön, wenn man per XMLHttpRequest XML anfordern, dies mittels XSL-Stylesheet formatieren und das Ergebnis an ein Element einfach an ein Element anhängen könnte. <- Wunsch!!!

Meine XML-Datei ist ganz einfach und hat einen Verweis auf ein XSL-Stylesheet:

lt;?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet href="xml2.xsl" type="text/xsl" ?>
<mee id="4711">
<mae attr="A12" pu="12">hugo</mae>
<mae attr="A12" pu="13">otto</mae>
</mee>

Das XSL-Stylesheet ist auch nicht umfangreich:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />

<xsl:template match="/">
<div>
<xsl:for-each select="//mae">
<xsl:value-of select="." />
<br />
</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>

Und nun sollen die beiden per Javascript verarbeitet werden, so dass das Ergebnis der XSL-Transformation an ein beliebiges Element angehangen werden kann:

<div id="myid">abc</div>
<script>
function LoadXMLwithXSL(xmlfile,tag_id){

// load the xml file
  var myXMLHTTPRequest = new XMLHttpRequest();
  myXMLHTTPRequest.open("GET", xmlfile, false);
  myXMLHTTPRequest.send(null);
  var xmlDoc = myXMLHTTPRequest.responseXML;
  if (xmlDoc.childNodes[0].nodeName == "xml")
    xmlDoc.removeChild(xmlDoc.childNodes[0]);
  xslfile = /href="(.+\.xsl)"/.exec(xmlDoc.childNodes[0].nodeValue)[1];

// load the xsl file
  myXMLHTTPRequest = new XMLHttpRequest();
  myXMLHTTPRequest.open("GET", xslfile, false);
  myXMLHTTPRequest.send(null);
  var xslStylesheet = myXMLHTTPRequest.responseXML;

  if (typeof XSLTProcessor != 'undefined') {      // firefox
    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(xslStylesheet);
    document.getElementById(tag_id).innerHTML = "";
    document.getElementById(tag_id).appendChild(
       xsltProcessor.transformToFragment(xmlDoc, document));
    }
  else if (typeof xmlDoc.transformNode != 'undefined') {     // IE
    document.getElementById(tag_id).innerHTML 
      = xmlDoc.transformNode(xslStylesheet);
    }
}
</script>
<a href='javascript:LoadXMLwithXSL("xml2.xml","myid")'>CLICK</a>

Auch hier muss man wieder für die beiden Browser Firefox und IE (die anderen hab ich nicht) unterschiedliche Wege gehen. Das fängt schon beim Laden der XML-Datei an, mal mit xml-Prolog mal ohne ... Ich hoffen, dass ich den Namen der XSL-Datei einigermaßen gut erwischt habe - im Zweifelsfall ist href vor type zu notieren (was ja kein wirkliches Problem sein sollte). In der XSL-Datei muß noch die xsl:output- Verarbeitungsinstruktion auf html gesetzt werden, sonst wird wieder ein unnötiger XML-Prolog generiert. Beim IE kann nun innerHTML verwendet werden, weil es sich ja um reine HTML-Elemente handelt und die verkraftet der IE ja bekanntlich so einigermaßen ... ich geh nun nicht weiter auf die Tags ein, wo es Ausnahmen gibt (man denke an Tabellen), denn dazu gibt ja hinreichend viele Kommentare im Web.

Diese Lösung mit dem automatischen Laden der XSL-Datei, in dem man die Verarbeitungsinstruktion auswertet, habe ich so bislang nirgends gefunden, obwohl es eigentlich nahe liegt, die Formatierung von XML auch in AJAX mittel XSL vorzunehmen. Also zumindest meinem Wunsch (!) bin ich mit dieser Lösung ziemlich nahe. Mal sehen, wie stabil sich die Lösung bewähren wird.

innerHTML und XML und die AJAX-Lib Prototype

Puh - hab ich einfach nicht gewußt, dass der Microsoft Internet Explorer bei einer innerHTML-Zuweisung von einem XML-String schlapp macht...

Da probiere ich die AJAX-Lib Prototype aus und finde eine ganz interessante Funktionalität, nämlich den Ajax.Updater. Der fordert sich eine Datei vom Server an und hängt sie an ein mit einem id-Attribut ausgestattetes Element dran.

var ajax = new Ajax.Updater(element, url, options)

Eigentlich ganz einfach und schön. Sofort ausprobiert und im Firefox angesehen. Super! Dann das ganze im IE: schrecklich!!! Probiere alles hin und her. Nichts zu machen. Meine XML-File wollte sich nicht ordentlich anhängen lassen. Also hinein in den Scriptcode bei Prototype und die Stelle gesucht, wo das ganze passiert. Hmmm ... da wird die Datei entgegengenommen und zum String gemacht und mit innerHTML ans betreffende Element gehangen. Hmmm ... sollte da der Wurm drin sein? Schnell ein kleines Beispiel getestet und siehe da, Firefox macht aus dem XML-String ne schöne DOM-Struktur und der IE nicht!!! Mal sehen was andere dazu sagen. Jaja ... es geht im IE net.

Also bin ich nicht der einzige; es wird sicherlich was fertiges geben. Nö, nicht wirklich. Als wäre das nicht was schönes :) Anleitungen zum selbst stricken en masse. Mir bleibt wohl nichts übrig. Ach da steht es ja auch bei Prototype: der Ajax.Updater geht nur mit (X)HTML ... Hmm, und für XML? Nichts dabei. Da dachte ich, es wäre schön, aber ...

Die Lösung in einem kleinen Skript:

<style>
first_name {font-size:24px}
</style>
<div id="a1">hallo</div>
<script>
function loadXMLstring(xmlstr) {
if (typeof DOMParser == "undefined") {
  var xml = new ActiveXObject("Microsoft.XMLDOM");
  xml.loadXML(xmlstr);
  domTree(xml.firstChild,document.getElementById("a1"));
  }
else {
  document.getElementById("a1").innerHTML += xmlstr;
  }
alert( document.getElementById("a1").innerHTML);
}

function domTree(tree,position) {
  var e = document.createElement(tree.nodeName);
  position.appendChild(e);
  if (tree.nodeValue) e.innerHTML=tree.nodeValue;
  for (var i=0; i<tree.attributes.length; i++) {
      var a = document.createAttribute(tree.attributes[i].nodeName);
      a.nodeValue = tree.attributes[i].nodeValue;
      e.setAttributeNode(a);
      }
  if (tree.hasChildNodes()) {
      for (var i=0; i<tree.childNodes.length; i++) 
         if (tree.childNodes[i].nodeName != "#text")
            domTree(tree.childNodes[i],e);
      }
}
</script>
<a href='javascript:loadXMLstring("
<customer pu=\"a1\" pa=\"123\">
<first_name>Joe</first_name>
<last_name id=\"4711\">Smith</last_name>
</customer>
")'>CLICK</a>

Ganz am Anfang der style-Tag ist nur zum Formatieren des XML. Dann das Element, an den der XML-String eingehangen wird mit der Id="a1". Die Funktion loadXMLstring(xmlstr) wird aus einem <a>-Element aktiviert und unterscheidet brav, ob es sich um IE oder Firefox handelt (weitere Browser hab ich nicht, also gibts dazu auch nichts). Beim else-Zweig sieht man, wie einfach man es sich beim Firefox machen kann. Der IE-Zweig lädt den XML-String in ein XML-DOM und ruft dann die Funktion domtree auf. Diese arbeitet den XML-String rekursiv ab, untersucht, ob die Elemente Inhalte und Attribute haben und hängt sie an das Browser-DOM dran. (Wer hierfür was besseres kennt, der soll mir mailen - hab leider keine Funktion bei Microsoft dafür gefunden ... auch sowas wie Nodecloning hat nicht funktioniert, aber vielleicht stell ich mich ja auch nur zu dumm an.) Irgendwie ist noch was nicht so schön beim Anhängen von TextNodes, da hab ich das gerade gebogen ... damit fallen die überfüssigen #text-Nodes weg.

Hab meine Prototype-Lib mit dieser Idee ergänzt und nun kann sie auch im Internet Explorer einen XML-Baum an ein Element meiner Wahl anhängen. Warum ist da noch keiner drauf gekommen? Was immer noch nicht schön ist, ist dass der Firefox die XML-Elemente brav und auch mit verbundenem style anzeigt und der IE nicht ...