frankx: XML PHP Entities Umlaute echo save

Hellihello

mit

  
<?php  
 $xml=<<<EOF  
<?xml version="1.0"?>  
<wurzel>  
&gt;Ü  
</wurzel>  
EOF;  
echo $xml;  
$doc=new DOMDocument;  
$doc->loadXML($xml);  
echo $doc->documentElement->nodeValue;  
echo $doc->saveXML();  
?>  

habe ich im im Eingabestring "&gt;Ü" erhalte als nodeValue ">Ü" und beim speichern kommt "&gt;&#xDC;" heraus, also das Ü auch vermutlich als utf-8 Entity gespeichert. Im Grund heißt das, solche Textpassagen  immer in CDATA abspeichern weil XML sonst nicht das abspeichert, was ich eingebe, oder?

dank und gruß,

frankx

  1. Hi,

    habe ich im im Eingabestring "&gt;Ü" erhalte als nodeValue ">Ü" und beim speichern kommt "&gt;&#xDC;" heraus, also das Ü auch vermutlich als utf-8 Entity gespeichert. Im Grund heißt das, solche Textpassagen  immer in CDATA abspeichern weil XML sonst nicht das abspeichert, was ich eingebe, oder?

    könntest Du diese Sätze bitte sprachlich und fachlich noch einmal überarbeiten? Das einzige, was ich verstanden zu haben glaube, ist dass Du meinst, XML würde etwas abspeichern, was aber nicht der Fall ist.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hellihello Cheatah,

      dank für Deine Antwort. Ich hoffte, dass ginge aus dem Code hervor. Dass ich nicht wirklich abspeicher, weiß ich, mit $doc->save("xml-test.xml") erhalte ich aber die selbe Ausgabe, dann im  File abgespeichert.

      Ansonsten wollt ich meinen:

      • im Eingabestring (xml-Dokument) gebe ich als Textknoten des Wurzelelementes "&gt;Ü" ein.

      • Wenn ich die als nodeValue des DOMDocument ausgebe, erhalte ich ">Ü" (also die Spitze-Klammer statt der HTML-Entity, wie sie im xml-String steht).

      • Und beim "speichern", ("echo" oder wirklich abgespeichert ist ja ident), kommt "&gt;&#xDC;" heraus, also das Ü auch vermutlich als utf-8 Entity gespeichert.

      Gruß,

      frankx

      1. Hi,

        • im Eingabestring (xml-Dokument) gebe ich als Textknoten des Wurzelelementes "&gt;Ü" ein.

        soweit klar.

        • Wenn ich die als nodeValue des DOMDocument ausgebe, erhalte ich ">Ü" (also die Spitze-Klammer statt der HTML-Entity, wie sie im xml-String steht).

        Das hast Du auf welche Weise überprüft?

        • Und beim "speichern", ("echo" oder wirklich abgespeichert ist ja ident), kommt "&gt;&#xDC;" heraus,

        Das hast Du auf welche Weise überprüft?

        also das Ü auch vermutlich als utf-8 Entity gespeichert.

        Nein, in UTF-8 ist das Ü bei 0xC39C zu finden.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hellihello

          Das hast Du auf welche Weise überprüft?
          Das hast Du auf welche Weise überprüft?

          ... indem ich es

          a) mit dem Editor Scite der php.exe übergeben habe (php 5.03)

          b) es auf einem Server als Script aufrufe und mit den ausgegebenen Quelltext anschaue (Zeile 3 Eingabe, Zeile 5 NodeValue Zeile 8 abspeichern) :

          <?xml version="1.0"?>
          <wurzel>
          &gt;Ü
          </wurzel>

          Ü

          <?xml version="1.0"?>
          <wurzel>
          &gt;&#xDC;
          </wurzel>

          Dank und Gruß,

          frankx

          1. Hi,

            <?xml version="1.0"?>
            <wurzel>
            &gt;Ü
            </wurzel>

            Ü
            <?xml version="1.0"?>
            <wurzel>
            &gt;&#xDC;
            </wurzel>

            ah, allmählich komme ich dahinter, was Du eigentlich wissen willst. Zurück zu Deinem Code:

            | $xml=<<<EOF
            | [...]

            Hier weist Du der Variable $xml einen String zu. Dieser hat noch nichts mit XML zu tun, deswegen ...

            | echo $xml;

            ... entspricht diese Ausgabe genau dem, was Du zuvor hattest.

            | $doc=new DOMDocument;
            | $doc->loadXML($xml);

            Nun lässt Du eine Analyse des Strings vornehmen, welche seine Einzelteile einem Objektmodell zuführt, wo diese in einer Form gespeichert werden, die als geeignet angesehen wird. Dabei wird insbesondere das "&gt;Ü" korrekt zu ">Ü" dekodiert,

            | echo $doc->documentElement->nodeValue;

            was hier ausgegeben wird.

            | echo $doc->saveXML();

            In dieser Methode wird das gespeicherte Objektmodell in ein gültiges XML umgewandelt. Das zuvor gespeicherte ">" ergibt nun korrekt zu "&gt;", das "Ü" wird in einer von vielen möglichen Formen als "&#xDC;" ausgeben.

            Cheatah

            --
            X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
            X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Hallo,

              <?xml version="1.0"?>
              <wurzel>
              &gt;Ü
              </wurzel>

              In dieser Methode wird das gespeicherte Objektmodell in ein gültiges XML umgewandelt.

              Genau das versucht PHP hier wohl.

              Das zuvor gespeicherte ">" ergibt nun korrekt zu "&gt;", das "Ü" wird in einer von vielen möglichen Formen als "&#xDC;" ausgeben.

              Naja so viele andere Möglichkeiten bleiben ja nicht für XML Zeichendaten.

              @frankx:
              Dein XML hat keine Encoding Deklaration. Deshalb gilt:
              Bei Abwesenheit von Informationen, die durch ein externes Transportprotokoll (z.B. HTTP oder MIME-Typ) geliefert werden, ist es ein Fehler, wenn ein Entity, welches eine Kodierungsdeklaration enthält, in einer anderen Kodierung an den XML-Prozessor übergeben wird. Ebenso ist es ein Fehler, wenn ein Entity, das weder mit einer Byte-Order-Markierung noch mit einer Kodierungsdeklaration beginnt, eine andere Kodierung als UTF-8 benutzt. Beachten Sie, dass wegen der Tatsache, dass ASCII eine Teilmenge von UTF-8 ist, ASCII-Entities nicht unbedingt eine Kodierungsdeklaration brauchen.

              Dein "Ü" steht offensichtlich nicht im UTF-8 encoding im String, sondern im ISO-8859-x encoding. PHP würde also fehlerhaftes XML erzeugen, würde es das Byte xDC einfach so im Dokument stehen lassen.

              Ein:

              <?xml version="1.0" encoding="ISO-8859-1"?>
              <wurzel>
               &gt;Ü
              </wurzel>

              wäre einen Versuch wert, eventuell verbunden mit einem
              $doc=new DOMDocument('1.0', 'iso-8859-1');.

              viele Grüße

              Axel

              1. Hellihello Axel,

                Ein:

                <?xml version="1.0" encoding="ISO-8859-1"?>
                <wurzel>
                &gt;Ü
                </wurzel>

                wäre einen Versuch wert, eventuell verbunden mit einem
                $doc=new DOMDocument('1.0', 'iso-8859-1');.

                Dann erhalte ich :

                <?xml version="1.0" encoding="ISO-8859-1"?>
                <wurzel>
                &gt;Ü
                </wurzel>

                Ü

                <?xml version="1.0" encoding="ISO-8859-1"?>
                <wurzel>
                &gt;Ü
                </wurzel>

                also als nodeValue ">Ü", in dem Fall auch den Editor auf 8-Bit umgestellt. Das hieße, das Abspeichern wäre ok, die Ausgabe aber murx. Also CDATA, denk ich mal, bei einem Mini-Content-Manager könnte ja auch mal eine Spitze Klammer oder ein Ampersand vorkommen, was das ganze dann zerschießt sonst, denn ein freihstendens "&" mag er garnicht.

                Dank,

                frankx

                1. Hallo frankx,

                  $doc=new DOMDocument('1.0', 'iso-8859-1');.
                  Dann erhalte ich :
                  [...]
                  Ü

                  ach was? Jetzt bin ich wirklich verblüfft. Denn die Bytefolge 'Ü' ist die UTF-8-Darstellung des Zeichens 'Ü'. Und das, obwohl du jetzt ausdrücklich ISO-8859-1 angibst? Seltsam.

                  Da ist noch irgendwas oberfaul, vielleicht sogar irgendeine Unfähigkeit von PHP, mit UTF-8 korrekt umzugehen. Aber ohne ein ausführliches Codebeispiel bleibt das wohl ein Ratespiel.

                  So long,
                   Martin

                  --
                  Man sollte immer wissen was man sagt
                   - aber auf keinen Fall alles sagen, was man weiß.
                  1. Hellihello Martin,

                      
                    <?php  
                     $xml=<<<EOF  
                    <?xml version="1.0" encoding="ISO-8859-1"?>  
                    <wurzel>  
                    &gt;Ü  
                    </wurzel>  
                    EOF;  
                    echo $xml;  
                    $doc=new DOMDocument('1.0', 'iso-8859-1');  
                    $doc->loadXML($xml);  
                    echo $doc->documentElement->nodeValue;  
                    echo $doc->saveXML();  
                    ?>  
                    
                    

                    bringt besagtes:

                    <?xml version="1.0" encoding="ISO-8859-1"?>
                    <wurzel>
                    &gt;Ü
                    </wurzel>

                    Ü

                    <?xml version="1.0" encoding="ISO-8859-1"?>
                    <wurzel>
                    &gt;Ü
                    </wurzel>

                    Gruß,
                    frankx

                    1. Hallo,

                      in welcher Codierung ist deine ursprüngliche PHP-Datei gespeichert? Etwa in UTF-8? Das würde bedeuten, dass die Bytefolge 'Ü' schon (korrekterweise) so im Script steht. PHP tut dann nichts weiter als Byte für Byte exakt wiederzugeben und hinterher den so erzeugten String, von dem du behauptest, er sei ISO-8859-1, unverändert auszugeben. Dann ist das Verhalten korrekt.

                      Als Lösung würde ich vorschlagen, entweder ALLES konsequent in UTF-8 zu halten, oder eben ALLES (auch das Script selbst!) in ISO-8859-1. Diese Mischformen führen anscheinend immer wieder zu Problemen an den Übergängen von einer Codierung zur anderen.

                      So long,
                       Martin

                      --
                      TEAM: Toll, Ein Anderer Macht's.
                      1. Hallo,

                        in welcher Codierung ist deine ursprüngliche PHP-Datei gespeichert? Etwa in UTF-8? Das würde bedeuten, dass die Bytefolge 'Ü' schon (korrekterweise) so im Script steht. PHP tut dann nichts weiter als Byte für Byte exakt wiederzugeben und hinterher den so erzeugten String, von dem du behauptest, er sei ISO-8859-1, unverändert auszugeben. Dann ist das Verhalten korrekt.

                        Hm, schau Dir nochmal das PHP-Script in https://forum.selfhtml.org/?t=130693&m=844996 an. Das ist _ein_ Script, welches _ein_ Dokument mit drei echo-Anweisungen an den Browser ausgibt. In zwei dieser echo-Anweisungen wird ein "Ü" korrekt in ISO-8859-x kodiert erzeugt. Nur die Anweisung:

                        echo $doc->documentElement->nodeValue;

                        erzeugt ein UTF-8-"Ü".

                        Als Lösung würde ich vorschlagen, entweder ALLES konsequent in UTF-8 zu halten,

                        ACK

                        oder eben ALLES (auch das Script selbst!) in ISO-8859-1.

                        Ja und dann eben:

                        echo utf8_decode($doc->documentElement->nodeValue);

                        für alle XML-DOM-Funktionen, die offensichtlich UTF-8 zurückliefern.

                        viele Grüße

                        Axel

                        1. Hallo Axel,

                          Hm, schau Dir nochmal das PHP-Script in https://forum.selfhtml.org/?t=130693&m=844996 an. Das ist _ein_ Script, welches _ein_ Dokument mit drei echo-Anweisungen an den Browser ausgibt.

                          in der ersten echo-Anweisung "muss" es korrekt wiedergegeben werden, egal ob das Dokument als UTF-8 oder ISO abgelegt ist. Hauptsache, der Server liefert es mit der richtigen Angabe zur Zeichencodierung aus.
                          Aber das zweite echo gibt etwas aus, das bereits von PHP verarbeitet wurde. Mir scheint es nach wie vor, dass der Eingabestring $xml, den loadXML() bekommt, schon ein UTF-8-codiertes Ü enthält, aber loadXML() geht davon aus, dass der String ISO-codiert ist und behandelt die beiden Bytes, die das Zeichen bilden, als einzelne Zeichen und konvertiert sie als zwei getrennte Sonderzeichen in UTF-8.
                          Dann greift frankx ja mit $doc->documentElement->nodeValue direkt auf die gespeicherten Strings zu und umgeht dabei eventuell eingebaute Rück-Codierungen, gibt also die zwei separaten Zeichen aus.
                          Beim Zugriff über saveXML() wird die Codierung wieder rückgängig gemacht: PHP "weiß", dass der String intern als UTF-8 gespeichert ist, aber an der Schnittstelle zum Script ISO ausgetauscht werden soll. Also werden die beiden separat in je zwei Bytes codierten Sonderzeichen wieder in ihr Äquivalent in ISO umgewandelt, der daraus entstehende String im HTML-Kontext als UTF-8 aufgefasst und nach zweimaliger falscher Umwandlung wieder richtig angezeigt.
                          Ist doch gar nicht so kompliziert ... ;-)

                          Ja und dann eben:
                          echo utf8_decode($doc->documentElement->nodeValue);
                          für alle XML-DOM-Funktionen, die offensichtlich UTF-8 zurückliefern.

                          Meiner Ansicht nach tun sie das eben nicht, sondern sie nehmen und geben genau das, was in new DOMDocument() definiert wurde.

                          Ciao,
                           Martin

                          --
                          Husten kann böse Folgen haben.
                          Besonders im Kleiderschrank.
                          1. Hallo,

                            hier die Aufklärung des encoding-Chaos (musste mir erst PHP5 installieren):

                            Der folgende PHP-Quellcode, gespeichert unter encoding UTF-8 (ohne BOM)

                              
                            <?php  
                            header('Content-Type:text/plain; charset=UTF-8');  
                             $xml=<<<EOF  
                            <?xml version="1.0"?>  
                            <wurzel>  
                            &gt;Ü  
                            </wurzel>  
                            EOF;  
                            echo $xml;  
                            $doc=new DOMDocument();  
                            $doc->loadXML($xml);  
                            echo $doc->documentElement->nodeValue;  
                            echo $doc->saveXML();  
                            ?>  
                            
                            

                            ergibt:
                            <?xml version="1.0"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Ü

                            <?xml version="1.0"?>
                            <wurzel>
                            &gt;&#xDC;
                            </wurzel>

                            PHP nutzt vorsichtshalber numerische Zeichenreferenzen, weil das XML keine klare encoding-Angabe hat. Darauf, dass UTF-8 Standard ist, verlassen sich die PHP-DOM-Programmierer offensichtlich nicht.
                            Beweis: Der leicht abgeänderte Code, wieder gespeichert unter encoding UTF-8 (ohne BOM)

                              
                            <?php  
                            header('Content-Type:text/plain; charset=UTF-8');  
                             $xml=<<<EOF  
                            <?xml version="1.0" encoding="UTF-8"?>  
                            <wurzel>  
                            &gt;Ü  
                            </wurzel>  
                            EOF;  
                            echo $xml;  
                            $doc=new DOMDocument();  
                            $doc->loadXML($xml);  
                            echo $doc->documentElement->nodeValue;  
                            echo $doc->saveXML();  
                            ?>  
                            
                            

                            ergibt:
                            <?xml version="1.0" encoding="UTF-8"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Ü

                            <?xml version="1.0" encoding="UTF-8"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Mit ISO-8859-1 encoding (auch der PHP-Quellcode ist jeweils ISO-encodiert) sieht das Ganze so aus:

                              
                            <?php  
                            header('Content-Type:text/plain; charset=ISO-8859-1');  
                             $xml=<<<EOF  
                            <?xml version="1.0" ?>  
                            <wurzel>  
                            &gt;Ü  
                            </wurzel>  
                            EOF;  
                            echo $xml;  
                            $doc=new DOMDocument();  
                            $doc->loadXML($xml);  
                            echo $doc->documentElement->nodeValue;  
                            echo $doc->saveXML();  
                            ?>  
                            
                            

                            ergibt:
                            <?xml version="1.0" ?>
                            <wurzel>
                            &gt;Ü
                            </wurzel><br />
                            <b>Warning</b>:  DOMDocument::loadXML() [<a href='function.DOMDocument-loadXML'>function.DOMDocument-loadXML</a>]: Input is not proper UTF-8, indicate encoding !
                            Bytes: 0xDC 0x0D 0x0A 0x3C in Entity, line: 3 in <b>D:\www\docs\test2.php</b> on line <b>11</b><br />
                            <?xml version="1.0"?>

                            Klar, das Byte 0xDC ist kein UTF-8. UTF-8 ist aber Standard, wenn kein encoding angegeben wurde.

                            Mit:

                              
                            <?php  
                            header('Content-Type:text/plain; charset=ISO-8859-1');  
                             $xml=<<<EOF  
                            <?xml version="1.0" encoding="ISO-8859-1"?>  
                            <wurzel>  
                            &gt;Ü  
                            </wurzel>  
                            EOF;  
                            echo $xml;  
                            $doc=new DOMDocument();  
                            $doc->loadXML($xml);  
                            echo $doc->documentElement->nodeValue;  
                            echo $doc->saveXML();  
                            ?>  
                            
                            

                            ergibt sich:
                            <?xml version="1.0" encoding="ISO-8859-1"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Ü

                            <?xml version="1.0" encoding="ISO-8859-1"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Meine Vermutung, dass [DOMDocument]->documentElement->nodeValue grundsätzlich UTF-8 zurückliefert, bestätigt sich.

                            Mit:

                              
                            <?php  
                            header('Content-Type:text/plain; charset=ISO-8859-1');  
                             $xml=<<<EOF  
                            <?xml version="1.0" encoding="ISO-8859-1"?>  
                            <wurzel>  
                            &gt;Ü  
                            </wurzel>  
                            EOF;  
                            echo $xml;  
                            $doc=new DOMDocument();  
                            $doc->loadXML($xml);  
                            echo utf8_decode($doc->documentElement->nodeValue);  
                            echo $doc->saveXML();  
                            ?>  
                            
                            

                            ergibt sich:
                            <?xml version="1.0" encoding="ISO-8859-1"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            Ü

                            <?xml version="1.0" encoding="ISO-8859-1"?>
                            <wurzel>
                            &gt;Ü
                            </wurzel>

                            viele Grüße

                            Axel

                2. Hallo,

                  Ein:

                  <?xml version="1.0" encoding="ISO-8859-1"?>
                  <wurzel>
                  &gt;Ü
                  </wurzel>

                  wäre einen Versuch wert, eventuell verbunden mit einem
                  $doc=new DOMDocument('1.0', 'iso-8859-1');.

                  Dann erhalte ich :

                  <?xml version="1.0" encoding="ISO-8859-1"?>
                  <wurzel>
                  &gt;Ü
                  </wurzel>

                  Ü

                  Aha, $doc->documentElement->nodeValue liefert also UTF-8 zurück. Das ist nicht wirklich überraschend, wo doch UTF-8 das Standard-encoding für XML ist.

                  <?xml version="1.0" encoding="ISO-8859-1"?>
                  <wurzel>
                  &gt;Ü
                  </wurzel>

                  also als nodeValue ">Ü",

                  Ja, ein "Ü" in UTF-8 im Browser als zwei Zeichen in ISO-8859-1 dargestellt. Stelle den Browser auf UTF-8, dann siehst Du ein Ü.

                  in dem Fall auch den Editor auf 8-Bit umgestellt.

                  Bitte? Heißt das vorher war der Quellcode-Text UFT-8 gespeichert? Dann ist das Ergebnis aber nicht erklärbar. Oder hieß das andere im Editor einfach Unicode? Das wäre dann UTF-16 oder ISO-10646-UCS-2.

                  Wenn Dein Editor UTF-8 speichern kann, dann wäre das konsequente Nutzen von UTF-8 wohl das Beste. Andererseits, wobei denkst Du würden Dich die numerischen Zeichenreferenzen, wie &#xDC; oder &#220; denn stören?

                  viele Grüße

                  Axel

              2. Hallo,

                Dein "Ü" steht offensichtlich nicht im UTF-8 encoding im String, sondern im ISO-8859-x encoding. PHP würde also fehlerhaftes XML erzeugen, würde es das Byte xDC einfach so im Dokument stehen lassen.

                Diese Vermutung war falsch, siehe https://forum.selfhtml.org/?t=130693&m=845078. Wenn das "Ü" ISO-8859-x encodiert gewesen wäre, würde ein Fehler erzeugt. Die automatische Umwandlung in numerische Zeichenreferenzen erfolgt, weil der Quellcode zwar UTF-8 encodiert ist, aber der XML-Prolog nicht explizit UTF-8 als encoding ausweist.

                viele Grüße

                Axel