Leeloo5E: DOMDocument mag Sonderzeichen nicht

Hallo,

Ich bastele mir grad in PHP ein XML-Dokument. Das klappt recht gut, bis auf eine Sache: Sonderzeichen verhindern die Darstellung des XML-Dokuments. Da hab ich mir gedacht, ich nehme htmlentities() und maskiere die Inhalte halt so. Aus ß wird so halt ß.
Das XML-Dokument wird damit korrekt erstellt. Im nächsten Schritt wird mit XSL ein HTML-Dokument erstellt und dieses verschluckt das ß bzw. ß ist nicht mehr da. "Sofortmaßnahmen" wird also zu "Sofortmanahmen".

Nun werdet ihr sagen: "Du brauchst eine Encodierung". Die Sache ist, ich hab die ja angegeben beim Erstellen des neuen XML-Dokuments mit DOM.

Ich gehe wie folgt vor:

  
// Creates an instance of the DOMImplementation class  
$imp = new DOMImplementation;  
  
// Creates a DOMDocumentType instance  
$dtd = $imp->createDocumentType('article', '', 'sdocbook.dtd');  
  
// Creates a DOMDocument instance  
$dom = $imp->createDocument("", "", $dtd);  
  
// Set encoding  
$dom->encoding = 'iso-8859-1';  
  
// Create an the root element  
$article = $dom->createElement('article');  
// Set an Attribute for root element  
$article->setAttribute('lang', 'de');  
// Append the root element  
$dom->appendChild($article);  
// Create Title Element  
$title = $dom->createElement('title', 'Sofortmaßnahmen');  
$article->appendChild($title);  
// Create SubTitle Element  
$subtitle = $dom->createElement('subtitle', 'Untertitel');  
$article->$dom->appendChild($subtitle);  
  
//Output created XML  
echo $dom->saveXML();  

Ja, und die Ausgabe sollte so aussehen, wegen dem "ß" in Sofortmaßnahmen meckert DOM jedoch rum und macht ab dem Zeichen nicht mehr weiter.

  
<?xml version="1.0" encoding="iso-8859-1"?>  
<!DOCTYPE article SYSTEM "sdocbook.dtd">  
<article lang="de">  
 <title>Sofortmaßnahmen</title>  
 <subtitle>Untertitel</subtitle>  
</article>  

In der DTD sind alle Sonderzeichen als Entities angegeben, so dass sie eigentlich akzeptiert werden sollten.
Das XSL zur Weitervearbeitung und Anzeige des XML als HTML ist ebenso in iso-8859-1. Stellt aber diese htmlentities-Darstellung der Sonderzeichen nicht da. Warum? Wieso werden die übergangen?

Als Zwischenschritt mach ich nun folgendes:

  
    $myxml = $dom->saveXML();  
    $myxml = html_entity_decode($myxml);  
  
    $xml = new DOMDocument();  
    $xml->resolveExternals = true;  
    $xml->loadXML($myxml);  
    echo $xml->saveXML();  

Damit werden die dekodierten HTMLEntities wieder in gewöhnliche Sonderzeichen umgewandelt und im Browser nach erfolgter XSL-Transformation korrekt angezeigt.

Gruß,
Leeloo

--
"Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
  1. hi,

    Nun werdet ihr sagen: "Du brauchst eine Encodierung". Die Sache ist, ich hab die ja angegeben beim Erstellen des neuen XML-Dokuments mit DOM.

    Und die Daten, die du ins Dokument einfügst, liegen auch in dieser Kodierung vor?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo,

      Nun werdet ihr sagen: "Du brauchst eine Encodierung". Die Sache ist, ich hab die ja angegeben beim Erstellen des neuen XML-Dokuments mit DOM.

      Und die Daten, die du ins Dokument einfügst, liegen auch in dieser Kodierung vor?

      hm ... gute Frage. Die liegen in der Datenbank und die interessierst nicht, ob da nun &szlig; oder ß steht. Deshalb geh ich da mit htmlentities oder html_entity_decode ran.

      Gruß,
      Leeloo

      --
      "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
      1. hi,

        Und die Daten, die du ins Dokument einfügst, liegen auch in dieser Kodierung vor?

        hm ... gute Frage. Die liegen in der Datenbank und die interessierst nicht, ob da nun &szlig; oder ß steht.

        Das hat ja auch nichts mit der Zeichenkodierung zu tun.

        Also suche erst mal die Antwort auf die "gute Frage".

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hallo,

          Das hat ja auch nichts mit der Zeichenkodierung zu tun.

          Also suche erst mal die Antwort auf die "gute Frage".

          Gibst du mir auch einen Tipp, wo ich da suchen soll! Bitte.

          Gruß,
          Leeloo

          --
          "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
          1. Hell-O!

            Also suche erst mal die Antwort auf die "gute Frage".
            Gibst du mir auch einen Tipp, wo ich da suchen soll! Bitte.

            In den Feld- bzw. Spalteneinstellungen der Datenbank. Stelle auch sicher, dass Datenbank und Script in der selben Codierung kommunizieren. Genaueres kann man nur sagen, wenn du uns das verwendete DBMS nebst Version nennst.

            Siechfred

            --
            Ich bin strenggenommen auch nur interessierter Laie. (molily)
            Siechfreds Tagebuch || Steuerfreie Geburtsbeihilfen? || RT 221 Erfurt-Altstadt i.V.
            1. Hallo,

              In den Feld- bzw. Spalteneinstellungen der Datenbank. Stelle auch sicher, dass Datenbank und Script in der selben Codierung kommunizieren. Genaueres kann man nur sagen, wenn du uns das verwendete DBMS nebst Version nennst.

              Hey, guter Tipp. Mein phpMyAdmin zeigt mir das ja och an. Der sagt:

              • MySQL-Zeichensatz: UTF-8
              • Zeichensatz / Kollation der MySQL-Verbindung: latin1_bin

              Und bei den Variablen, ist UTF-8 für character set client, character set results und character set server angegeben. Ich denke mal daran liegts. Mal schaun, müsst ich ja irgendwo ändern können. Ich hoffe, dass klappt dann auch.

              Das angegebene Skript im Anfangsposting, nimmt zu Testzwecken keine Daten aus der DB. Ich habe dort ein neues Element einfach so angelegt mit $dom->createElement('title', 'Sofortmaßnahmen');. Liegt das jetzt am CharacterSet meines Skripts? Wie stellt man das da ein? Eigentlich sage ich doch bei der Erstellung des neuen XML-Dokuments: sei iso-8859-1. Das sollte ihm doch reichen, oder? Das Dokument, wird am Ende zusammengebastelt $dom->saveXML(); in eben diesem Zeichensatz und das kann doch bekanntlich ü's, ä's oder ö's sowie das ß.

              Gruß,
              Leeloo

              --
              "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
              1. Hallo,

                dumm, dass man seine eigenen Threads nicht bearbeiten kann, um z.B. Text hinzuzufügen, weil man noch was vergessen hat.

                Meine derzeitige MySQL-Version: 5.0.24a.

                Und bei den Variablen, ist UTF-8 für character set client, character set results und character set server angegeben. Ich denke mal daran liegts. Mal schaun, müsst ich ja irgendwo ändern können. Ich hoffe, dass klappt dann auch.

                So, mal eben in die mysql.cnf geschaut. Da steht merkwürdigerweise für character-set-server: latin1. phpMyAdmin zeigt mir eben utf-8

                Gruß,
                Leeloo

                --
                "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
                1. echo $begrüßung;

                  dumm, dass man seine eigenen Threads nicht bearbeiten kann, um z.B. Text hinzuzufügen, weil man noch was vergessen hat.

                  Dumm wäre es, wenn ich die unkorrigierte Version gelesen, mich darauf bezogen hätte und dann dieser Bezug verschwindet. Das stiftet mehr Verwirrung als es nützt.

                  Und bei den Variablen, ist UTF-8 für character set client, character set results und character set server angegeben. Ich denke mal daran liegts. Mal schaun, müsst ich ja irgendwo ändern können. Ich hoffe, dass klappt dann auch.
                  So, mal eben in die mysql.cnf geschaut. Da steht merkwürdigerweise für character-set-server: latin1. phpMyAdmin zeigt mir eben utf-8

                  Schau bitte nochmal genau hin, was der phpMyAdmin anzeigt. Die Werte der Defaulteinstellungen des Servers können von den für die aktuelle Session eingestellten Werten abweichen. Session-Werte, die der PMA anzeigt sind für andere Clients nicht weiter interessant, die haben ihre eigenen Werte in ihrer Session.

                  Die einfachste Lösung ist, nach dem Connect ein SET NAMES latin1 oder SET NAMES utf8 an den Server zu senden, um für beide Seiten verbindlich festzulegen, in welcher Zeichenkodierung die Kommunikation zwischen Client und Server zu erfolgen hat.
                  Zu Hintergründen kannst du das MySQL-Handbuch-Kapitel Character Set Support lesen (und auch das hiesige Archiv befragen).

                  echo "$verabschiedung $name";

                  1. Hallo,

                    Vielen Dank.

                    Zu Hintergründen kannst du das MySQL-Handbuch-Kapitel Character Set Support lesen (und auch das hiesige Archiv befragen).

                    Hab ich beides bereits gemacht.

                    Gruß,
                    Leeloo

                    --
                    "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra
              2. Hallo,

                Das angegebene Skript im Anfangsposting, nimmt zu Testzwecken keine Daten aus der DB. Ich habe dort ein neues Element einfach so angelegt mit $dom->createElement('title', 'Sofortmaßnahmen');. Liegt das jetzt am CharacterSet meines Skripts? Wie stellt man das da ein?

                Ja, liegt es! Es ist vermutlich ISO-8859-1-kodiert, das ist ein Problem.

                Wenn du das Script im Editor speicherst, erlaubt dir der Editor meist, die Kodierung zu wählen, in der gespeichert werden soll.

                Eigentlich sage ich doch bei der Erstellung des neuen XML-Dokuments: sei iso-8859-1. Das sollte ihm doch reichen, oder?

                Nein, das ist anscheinend so:

                • Intern verwendet das PHP-DOM immer UTF-8 (bzw. richtig intern wohl UTF-16 o.ä.), egal was du für ein encoding setzt. Die gesetzte encoding wird bei der Arbeit mit dem DOM überhaupt nicht beachtet.
                • Wenn du Daten ins DOM einbringst, muss dies *immer* in UTF-8 geschehen. Wenn du Daten aus dem DOM holst, sind die *immer* UTF-8 kodiert. (Meiner Erfahrung nach. Vielleicht kann man es irgendwie ändern, jedenfalls nicht mit $dom->encoding.)
                • Die encoding wird nur dann beachtet, wenn du das Dokument serialisierst. Dann werden die Zeichen automatisch in die angegebene Kodierung umgewandelt.

                Das heißt:

                • Es ist okay, wenn du aus der Datenbank rohe UTF-8-Daten bekommst. Die kannst du problemlos direkt ins DOM schreiben. Entity-Maskierung solltest du dann natürlich lassen.
                • Das Serialisieren nach ISO-8859-1 sollte dann auch klappen.
                • PHP-Scripte, die mit dem DOM arbeiten und selbst hartkodierte Zeichendaten enthalten, sollten allesamt UTF-8-kodiert sein. Konkret, wenn du ein Script mit einem String mit Umlauten drin hast und die in ein DOM montieren willst, so darf das Script nicht ISO-8859-1-kodiert sein.
                • Die Anweisung $dom->encoding = 'iso-8859-1'; ist überhaupt nicht maßgeblich dafür, in welcher Kodierung Daten von den DOM-Methoden entgegengenommen werden. Diese Anweisung muss nicht vor allen anderen Operationen stehen, sie kann auch direkt vor dem saveXML()-Aufruf stehen, das hat denselben Effekt.

                Beispiel in ASCII mit Escape-Sequenzen:

                // ISO-8859-1-kodiertes ß im String  
                $title = $dom->createElement('title', "Sofortma\xDFnahmen");  
                // Führt immer zu einem Fehler!  
                  
                // UTF-8-kodiertes ß im String  
                $title = $dom->createElement('title', "Sofortma\xC3\x9Fnahmen");  
                // Funktioniert unabhängig vom letztlichen encoding des serialisierten Dokuments
                

                Mathias

                --
                »No nations, no borders.«
                SELFHTML Weblog
                1. Hallo Matthias,

                  Vielen Dank für die ausführliche Beschreibung. Jetzt ist doch einiges klarer.

                  Gruß,
                  Leeloo

                  --
                  "Als es noch keine Computer gab, war das Programmieren noch relativ einfach." - Edsger W. Dijkstra