Gabriel: Entityumwandlungen

Hallo,

ich möchte HTML-Code zuerst in einer XML zwischenspeichern und später dann wieder auslesen und als HTML-Code ausgeben.
Das problem bei der Sache ist, dass ich nicht einfach alle ISO-8859-1-Sonderzeichen zum speichern in ihre Entities konvertieren kann. Denn der XML-Parser meckert zurecht, wenn er Sachen wie "ä" vorfindet, da das nicht XML-konform ist. XML kennt ja nur die Eintities """, "&", "'", "<" und ">".

  1. Also soll ein "ä" eben nicht in "ä", sondern in "ä" umgewandelt werden. Das sollte per get_html_translation_table gehen. Das Beispiel auf php.net lautet:
$trans = get_html_translation_table(HTML_ENTITIES);  
$str = "Hallo & <Frau> & Krämer";  
$encoded = strtr($str, $trans);

Das Ergebnis sollte laut php.net folgendes sein:
Hallo &amp;amp; &amp;lt;Frau&amp;gt; &amp;amp; Kr&amp;auml;mer

Mein Apache spuckt jedoch immer folgendes aus:
Hallo &amp; &lt;Frau&gt; &amp; Kr&auml;mer

Es wird also nicht doppelt umgewandelt - woran könnte das liegen?

  1. Die Umwandlung lässt sich mit einer Sonderbehandlung für die fünf validen XML-Entities in den Griff bekommen. Aber bei der zurückwandlung habe ich genau das umgekehrte Problem.
$trans = get_html_translation_table(HTML_ENTITIES);  
$str = "Hallo &amp;amp; &amp;lt;Frau&amp;gt; &amp;amp; Kr&amp;auml;mer";  
$encoded = strtr($str, array_flip($trans));

Jedoch ist das Ergebnis nicht wie gewünscht eine einfache Umwandlung:
Aus: "Hallo &amp;amp; &amp;lt;Frau&amp;gt; &amp;amp; Kr&amp;auml;mer"
Sollte werden: "Hallo &amp; &lt;Frau&gt; &amp; Kr&auml;mer"

Sondern eine doppelte Umwandlung:
Aus: "Hallo &amp;amp; &amp;lt;Frau&amp;gt; &amp;amp; Kr&amp;auml;mer"
Wird: "Hallo & <Frau> & Krämer";

Eine Umwandlung mit str_replace statt strtr führt zum selben Ergebnis,
obwohl in php.net steht "strtr() [...] verändert bereits durchgeführte Ersetzungen *NICHT*. "

Wäre super, wenn mir da jemand weiterhelfen würde. Im voraus schon vielen Dank.

Gruß
Gabriel

  1. Moin!

    ich möchte HTML-Code zuerst in einer XML zwischenspeichern und später dann wieder auslesen und als HTML-Code ausgeben.

    Verpacke es in <![CDATA[ ]]>.

    Das problem bei der Sache ist, dass ich nicht einfach alle ISO-8859-1-Sonderzeichen zum speichern in ihre Entities konvertieren kann. Denn der XML-Parser meckert zurecht, wenn er Sachen wie "&auml;" vorfindet, da das nicht XML-konform ist. XML kennt ja nur die Eintities "&quot;", "&amp;", "&apos;", "&lt;" und "&gt;".

    Es ist überflüssig, solche Zeichen in Entities zu verpacken. Aber wenn du auf CDATA verzichtest, musst du in der Tat alle im HTML-Quelltext enthaltenen Zeichen, die in XML Sonderbedeutung haben, als Entity schreiben. htmlspecialchars() mit der passenden Option reicht da vollkommen aus - alternativ benutzt du eine passende XML-Klasse (z.B. DOM), der du einfach den HTML-Quelltext als Knoteninhalt übergibst - die Klasse sorgt dann für den korrekten Aufbau des XML.

    1. Die Umwandlung lässt sich mit einer Sonderbehandlung für die fünf validen XML-Entities in den Griff bekommen. Aber bei der zurückwandlung habe ich genau das umgekehrte Problem.

    Wie greifst du denn auf das gespeicherte XML zu? Doch hoffentlich nicht nackt auf den Quelltext.

    - Sven Rautenberg

    1. Moin!

      Verpacke es in <![CDATA[ ]]>.

      Das wollte ich eigentlich vermeiden.

      Es ist überflüssig, solche Zeichen in Entities zu verpacken. Aber wenn du auf CDATA verzichtest, musst du in der Tat alle im HTML-Quelltext enthaltenen Zeichen, die in XML Sonderbedeutung haben, als Entity schreiben. htmlspecialchars() mit der passenden Option reicht da vollkommen aus - alternativ benutzt du eine passende XML-Klasse (z.B. DOM), der du einfach den HTML-Quelltext als Knoteninhalt übergibst - die Klasse sorgt dann für den korrekten Aufbau des XML.

      »»

      Wie greifst du denn auf das gespeicherte XML zu? Doch hoffentlich nicht nackt auf den Quelltext.

      Ok, das bringt mich schon deutlich weiter. Ich habe noch nicht viel XML-Erfahrung.

      Die ersten Test-XMLs habe ich von Hand geschrieben. Das Script greift per SimpleXML auf die Daten zu, ich bin aber nicht davon ausgegangen, dass die Daten automatisch umgewandelt werden wenn ich sie per SimpleXML lade, ändere oder speichere.
      Das werde ich gleich mal ausprobieren. Danke!

      Gruß
      Gabriel

      1. Moin!

        Es ist überflüssig, solche Zeichen in Entities zu verpacken. Aber wenn du auf CDATA verzichtest, musst du in der Tat alle im HTML-Quelltext enthaltenen Zeichen, die in XML Sonderbedeutung haben, als Entity schreiben. htmlspecialchars() mit der passenden Option reicht da vollkommen aus - alternativ benutzt du eine passende XML-Klasse (z.B. DOM), der du einfach den HTML-Quelltext als Knoteninhalt übergibst - die Klasse sorgt dann für den korrekten Aufbau des XML.
        »»
        Die ersten Test-XMLs habe ich von Hand geschrieben. Das Script greift per SimpleXML auf die Daten zu, ich bin aber nicht davon ausgegangen, dass die Daten automatisch umgewandelt werden wenn ich sie per SimpleXML lade, ändere oder speichere.
        Das werde ich gleich mal ausprobieren. Danke!

        Ich habe es gerade getestet. Aber mir scheint als wäre SimpleXML keine in deinem Sinne "geeignete Klasse"?

        Kurz vorweg: $xml ist eine Klasse in der xmlfile wie folgt mit Inhalt befüllt wird:
        $this->xmlfile = simplexml_load_file('test.xml');

        Wenn ich folgendes mache:
        $xml->xmlfile->addChild("Child", "No02.&amp;ö<a");
        Dann hat das Kind "Child" den Wert "No02.", d.h. ab dem ersten Sonderzeichen wird alles abgeschnitten.

        Und bei folgender Aktion:
        $xml->xmlfile->addChild("Child", "No02.&amp;ö<a#");
        Wird ein inhaltsleeres Kind hinzugefügt...

        Das ist nicht das, was du mit "eine passende XML-Klasse, der du einfach den HTML-Quelltext als Knoteninhalt übergibst - die Klasse sorgt dann für den korrekten Aufbau des XML." meintest, oder?

        Gruß
        Gabriel

        1. Moin!

          Ich habe es gerade getestet. Aber mir scheint als wäre SimpleXML keine in deinem Sinne "geeignete Klasse"?

          Scheint so. In den Kommentaren zu addChild steht ein Kommentar, der addCData() implementiert und dazu die Extension DOM benutzt.

          Wenn ich folgendes mache:
          $xml->xmlfile->addChild("Child", "No02.&amp;ö<a");
          Dann hat das Kind "Child" den Wert "No02.", d.h. ab dem ersten Sonderzeichen wird alles abgeschnitten.

          Und bei folgender Aktion:
          $xml->xmlfile->addChild("Child", "No02.&amp;ö<a#");
          Wird ein inhaltsleeres Kind hinzugefügt...

          Wo ist da jetzt der große Unterschied? Im Hash # am Ende?

          Das ist nicht das, was du mit "eine passende XML-Klasse, der du einfach den HTML-Quelltext als Knoteninhalt übergibst - die Klasse sorgt dann für den korrekten Aufbau des XML." meintest, oder?

          Nein. SimpleXML ist halt nur für simple Dinge - dass das an sooo simplen Dingen scheitert, hätte ich nicht unbedingt erwartet, aber so ist das Leben halt.

          - Sven Rautenberg

          1. Moin,

            Scheint so. In den Kommentaren zu addChild steht ein Kommentar, der addCData() implementiert und dazu die Extension DOM benutzt.

            Danke für den Tipp. Das wäre unter Umstanden eine Lösung, auch wenn ich noch etwas skeptisch mit dem CDATA bin. Und dann müsste ich auch andere Funktionsnamen erstellen, damit z.B. auch bei Sachen wie simplexml_load_file nicht die Klasse SimpleXML, sondern die Klasse SimpleXMLExtended greift.

            Wo ist da jetzt der große Unterschied? Im Hash # am Ende?

            Genau, das ist der einzige Unterschied. Das verwundert mich etwas.

            SimpleXML ist halt nur für simple Dinge - dass das an sooo simplen Dingen scheitert, hätte ich nicht unbedingt erwartet, aber so ist das Leben halt.

            Und ich hatte gehofft damit eine einfache Schnittstelle schaffen zu können. Da ich nicht auf SQlite zurückgreifen kann habe ich XML im Visier. Und SimpleXML, da ich auch schon etwas kleineres direkt mit DOM gemacht habe das mich ehrlich gesagt nicht gerade angesprochen hat.

            Gruß
            Gabriel

      2. Moin!

        Verpacke es in <![CDATA[ ]]>.

        Das wollte ich eigentlich vermeiden.

        Warum? Jeder XML-Parser kann damit transparent umgehen, genauso wie er es mit Entities tun muß.

        - Sven Rautenberg

  2. @@Gabriel:

    nuqneH

    XML kennt ja nur die Eintities "&quot;", "&amp;", "&apos;", "&lt;" und "&gt;".

    Du könntest deinem XML aber andere Eintities beibringen:

    <!DOCTYPE foo  
      [  
        <!ENTITY auml "ä">  
        <!ENTITY ouml "ö">  
        <!-- Liste aller Entities, die du benötigst -->  
      ]  
    
    >
    
    

    Aber wie Sven schon sagte: Das ist unnötig.

    1. Also soll ein "ä" eben nicht in "&auml;", sondern in "&amp;auml;" umgewandelt werden.

    Nein. Ein 'ä' sollte gar nicht umgewandelt werden. Es sollte als 'ä' im ursprünglichen HTML, im XML zwischendurch und im generierten HTML stehen.

    „Es ist fast immer besser, eine Zeichencodierung zu benutzen, die es erlaubt, die Zeichen in ihrer normalen Form zu verwenden, anstatt Zeichen-Entity-Referenzen oder numerische Zeichenreferenzen zu verwenden.“ [QA-ESCAPES]

    Qapla'

    --
    Alle Menschen sind klug. Die einen vorher, die anderen nachher. (John Steinbeck)
    1. Hallo Gunnar,

      Du könntest deinem XML aber andere Eintities beibringen:

      <!DOCTYPE foo

      [
          <!ENTITY auml "ä">
          <!ENTITY ouml "ö">
          <!-- Liste aller Entities, die du benötigst -->
        ]

        
      Das wäre eine Möglichkeit, aber wenn man alle möglichen Entities brücksichtigen will bläht das die XML sehr auf.  
        
      
      > Ein 'ä' sollte gar nicht umgewandelt werden. Es sollte als 'ä' im ursprünglichen HTML, im XML zwischendurch und im generierten HTML stehen.  
      >   
      > „Es ist fast immer besser, eine Zeichencodierung zu benutzen, die es erlaubt, die Zeichen in ihrer normalen Form zu verwenden, anstatt Zeichen-Entity-Referenzen oder numerische Zeichenreferenzen zu verwenden.“ [[QA-ESCAPES](http://www.w3.org/International/questions/qa-escapes)]  
        
      Kennst du eine Möglichkeit, wie man ohne <![CDATA[ ]]> und ohne das Hinzufügen von Entitydeklarationen in der XML dem SimpleXML beibringen kann, dass er das 'ä' fressen soll ohne einen Fehler zu produzieren?  
        
      Das wäre für mich gerade das Optimum, aber leider kenne ich keinen Weg dahin...  
        
      Gruß  
      Gabriel
      
  3. Hi!

    ich möchte HTML-Code zuerst in einer XML zwischenspeichern und später dann wieder auslesen und als HTML-Code ausgeben.
    Das problem bei der Sache ist, dass ich nicht einfach alle ISO-8859-1-Sonderzeichen zum speichern in ihre Entities konvertieren kann.

    XML und alle(? - zumindest alle unter PHP) XML-Software kommt am besten mit UTF-8 zurecht. Wenn du es also mit UTF-8-Daten fütterst und auch solche als Rückgabe erwartest, wirst du die wenigsten Probleme bekommen. Zu Beachten übrig bleiben dann nur noch die Zeichen: <>&"'

    Lo!