46 votes

La génération du document XML en PHP (caractères d'échappement)

Je suis de la génération d'un document XML à partir d'un script PHP et j'ai besoin d'échapper les caractères spéciaux XML. Je sais que la liste de caractères doivent être échappés; mais quelle est la bonne façon de le faire?

Devrait les caractères doivent être échappés juste avec la barre oblique inverse (\') ou ce qui est la bonne façon? Est-il intégré dans la fonction PHP qui peut gérer cela pour moi?

36voto

Tomas Jancik Points 988

J'ai créé une fonction simple qui s'échappe avec les cinq "des entités prédéfinies" qui sont en XML:

function xml_entities($string) {
    return strtr(
        $string, 
        array(
            "<" => "&lt;",
            ">" => "&gt;",
            '"' => "&quot;",
            "'" => "&apos;",
            "&" => "&amp;",
        )
    );
}

Exemple d'utilisation de la Démo:

$text = "Test &amp; <b> and encode </b> :)";
echo xml_entities($text);

Sortie:

Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)

Un effet similaire peut être obtenu par l'utilisation d' str_replace , mais elle est fragile en raison de la double-replacings (non testé, non recommandé):

function xml_entities($string) {
    return str_replace(
        array("&",     "<",    ">",    '"',      "'"),
        array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;"), 
        $string
    );
}

34voto

Ionuț G. Stan Points 62482

Utiliser le DOM classes pour générer de l'ensemble de votre document XML. Il va traiter les codages et décodages que nous ne voulons même pas à s'inquiéter.


Edit: Cela a été critiqué par @Tchalvak:

L'objet DOM crée un document XML complet, il ne se laisse pas facilement se prêter à la juste codant pour une chaîne sur son propre.

Ce qui est faux, DOMDocument peut correctement la sortie d'un fragment de ne pas la totalité de ce document:

$doc->saveXML($fragment);

ce qui donne:

Test &amp; <b> and encode </b> :)
Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)

comme dans:

$doc = new DOMDocument();
$fragment = $doc->createDocumentFragment();

// adding XML verbatim:
$xml = "Test &amp; <b> and encode </b> :)\n";
$fragment->appendXML($xml);

// adding text:
$text = $xml;
$fragment->appendChild($doc->createTextNode($text));

// output the result
echo $doc->saveXML($fragment);

Voir La Démo

17voto

MarcDefiant Points 2398

Quel est le htmlspecialchars() fonction?

htmlspecialchars($input, ENT_QUOTES | ENT_XML1, $encoding);

Remarque: l' ENT_XML1 indicateur n'est disponible que si vous avez de PHP 5.4.0 ou plus.

htmlspecialchars() avec ces paramètres remplace les caractères suivants:

  • & (commercial) devient &amp;
  • " (double quote) devient &quot;
  • ' (single quote) devient &apos;
  • < (inférieur à) devient &lt;
  • > (supérieur à) devient &gt;

Vous pouvez obtenir la table de traduction à l'aide de la get_html_translation_table() fonction.

13voto

Josh Sunderman Points 71

Essayé difficile de traiter avec de l'entité XML problème, le résoudre de cette façon:

htmlspecialchars($value, ENT_QUOTES, 'UTF-8')

5voto

Capilé Points 631

Afin d'avoir un valide XML final du texte, vous devez échapper à toutes les entités XML et le texte écrit dans le même encodage que le document XML processing-instruction unis (le "codage" dans l' <?xml ligne). Les caractères accentués n'avez pas besoin d'être échappé aussi longtemps qu'ils sont codés comme le document.

Cependant, dans de nombreuses situations tout simplement échapper à la saisie avec htmlspecialchars peut entraîner une double codé entités (par exemple, &eacute; deviendrait &amp;eacute;), alors je vous suggère de décodage des entités html en premier:

function xml_escape($s)
{
    $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
    $s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
    return $s;
}

Maintenant, vous devez vous assurer que tous les caractères accentués sont valables dans le codage du document XML. Je vous encourage fortement à toujours coder sortie XML en UTF-8, car pas tous les parseurs XML respecter le document XML processing-instruction de codage. Si votre entrée peut venir d'un jeu de caractères différent, essayez d'utiliser utf8_encode().

Il y a un cas spécial, qui est votre entrée peut provenir de l'une de ces codages: ISO-8859-1, ISO-8859-15, UTF-8, cp866, cp1251, cp1252, et KOI8-R -- PHP traite tous de la même manière, mais il y a quelques légères différences entre eux-dont certains même iconv() ne peut pas gérer. Je ne pouvais résoudre ce problème de codage en complétant utf8_encode() comportement:

function encode_utf8($s)
{
    $cp1252_map = array(
    "\xc2\x80" => "\xe2\x82\xac",
    "\xc2\x82" => "\xe2\x80\x9a",
    "\xc2\x83" => "\xc6\x92",
    "\xc2\x84" => "\xe2\x80\x9e",
    "\xc2\x85" => "\xe2\x80\xa6",
    "\xc2\x86" => "\xe2\x80\xa0",
    "\xc2\x87" => "\xe2\x80\xa1",
    "\xc2\x88" => "\xcb\x86",
    "\xc2\x89" => "\xe2\x80\xb0",
    "\xc2\x8a" => "\xc5\xa0",
    "\xc2\x8b" => "\xe2\x80\xb9",
    "\xc2\x8c" => "\xc5\x92",
    "\xc2\x8e" => "\xc5\xbd",
    "\xc2\x91" => "\xe2\x80\x98",
    "\xc2\x92" => "\xe2\x80\x99",
    "\xc2\x93" => "\xe2\x80\x9c",
    "\xc2\x94" => "\xe2\x80\x9d",
    "\xc2\x95" => "\xe2\x80\xa2",
    "\xc2\x96" => "\xe2\x80\x93",
    "\xc2\x97" => "\xe2\x80\x94",
    "\xc2\x98" => "\xcb\x9c",
    "\xc2\x99" => "\xe2\x84\xa2",
    "\xc2\x9a" => "\xc5\xa1",
    "\xc2\x9b" => "\xe2\x80\xba",
    "\xc2\x9c" => "\xc5\x93",
    "\xc2\x9e" => "\xc5\xbe",
    "\xc2\x9f" => "\xc5\xb8"
    );
    $s=strtr(utf8_encode($s), $cp1252_map);
    return $s;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X