Erreur d'parsing XML: entité non définie

J'ai cherché stackoverflow sur ce problème et j'ai trouvé quelques sujets, mais je pense qu'il n'y a pas vraiment une réponse solide pour moi à ce sujet.

J'ai un formulaire que les users soumettent et la valeur du champ est stockée dans un file XML. Le format XML doit être codé avec UTF-8.

De time en time, un user copyra / cola du text de quelque part et c'est alors que je reçois l'erreur "entité non définie".

Je me rend count que XML ne prend en charge que quelques entités sélectionnées et que rien d'autre n'est reconnu – d'où l'erreur de l'parsingur.

D'après ce que je vois, il y a quelques options que j'ai vues:

  1. Je peux find et replace tous les   et les échanger avec ou un espace réel.
  2. Je peux placer le code en question dans une section CDATA.
  3. Je peux inclure ces entités dans le file XML.

Ce que je fais avec le file XML, c'est que l'user peut entrer du contenu dans un formulaire, il est stocké dans un file XML et que le contenu s'affiche alors sous forme de XHTML sur une page Web (analysé avec SimpleXML).

Parmi les trois options, ou toute autre option (s) dont je ne suis pas au courant, quelle est vraiment la meilleure façon de traiter ces entités?

Merci Ryan

METTRE À JOUR

Je tiens à remercier tout le monde pour les excellents commentaires. J'ai effectivement déterminé ce qui a causé l'erreur de ma personne. Toutes les suggestions m'ont fait examiner plus profondément!

Quelques boîtes de text où les anciennes boîtes de text, mais mes zones de text ont été améliorées avec TinyMCE. Il s'avère, tout en regardant de plus près, que les avertissements PHP ont toujours fait reference aux données des zones de text améliorées de TinyMCE. Plus tard, j'ai remarqué sur un PC que tous les personnages ont été retirés (parce qu'il ne pouvait pas les lire), mais sur un MAC, vous pouvez voir de petites cases carrées référençant le numéro unicode de ce personnage. La raison pour laquelle il est apparu en carrés sur un MAC en premier lieu, c'est parce que j'ai utilisé utf8_encode pour coder des données qui n'étaient pas dans UTF pour empêcher d'autres erreurs d'parsing (ce qui est en quelque sorte également lié à TinyMCE).

La solution à tout cela était assez simple:

J'ai ajouté cette entity_encoding : "utf-8" ligne entity_encoding : "utf-8" dans my tinyMCE.init. Maintenant, tous les personnages montrent la façon dont ils sont supposés.

Je suppose que la seule chose que je ne comprends pas, c'est pourquoi les personnages apparaissent encore lorsqu'ils sont placés dans des zones de text, car rien ne les convertit en UTF, mais avec TinyMCE, c'était un problème.

Je conviens qu'il s'agit uniquement d'un problème de encoding. En PHP, c'est ainsi que j'ai résolu ce problème:

  1. Avant de passer le fragment html au constructor SimpleXMLElement je l'ai décodé en utilisant html_entity_decode .

  2. Ensuite, l'encodé en utilisant utf8_encode() .

 $headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; $xmlHeader = new SimpleXMLElement($headerDoc); $ headerDoc = '<temp>'. $headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; $xmlHeader = new SimpleXMLElement($headerDoc); utf8_encode (html_entity_decode ($ headerFragment)). $headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; $xmlHeader = new SimpleXMLElement($headerDoc); '</ temp>'; $headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; $xmlHeader = new SimpleXMLElement($headerDoc); 

Maintenant, le code ci-dessus ne lance aucune erreur d' entité indéfinie .

Vous pouvez parsingr HTML le text et l'avoir ré-échappé uniquement avec les entités numériques respectives (comme: &nbsp;&#160; ). En tout cas – simplement utiliser une input désinfectée des users est une mauvaise idée.

Toutes les entités numériques sont autorisées en XML, seuls les nommés connus de HTML ne fonctionnent pas (à l'exception de &amp; , &quot; &lt; , &gt; , &apos; ).

La plupart du time, vous pouvez simplement écrire le caractère réel ( &ouml;ö ) dans le file XML afin qu'il n'y ait aucun besoin d'utiliser une reference entière. Si vous utilisez une API DOM pour manipuler votre XML (et vous devriez!), C'est votre pari le plus sûr.

Enfin (c'est la solution de développeur paresseux), vous pouvez build un file XML cassé (c.-à-d. Pas bien formé, avec des erreurs d'entité) et simplement passer à l'ordre pour les correctifs nécessaires. Cela peut fonctionner ou échouer en fonction de ce qui est tout cassé. D'après mon expérience, la propreté est assez judicieuse, et vous permet de sortir avec beaucoup.

1 . Je peux find et replace tout [ &nbsp; ?] et les échanger avec [ &#160; ?] ou un espace réel.

Il s'agit d'une méthode robuste, mais il vous faut avoir un tableau de toutes les entités HTML (je suppose que l'input collée provient de HTML) et d'parsingr le text collé pour les references d'entité.

2 . Je peux placer le code en question dans une section CDATA.

En d'autres termes, désactiver l'parsing pour toute la section? Ensuite, vous devriez l'parsingr d'une autre manière. Pourait marcher.

3 . Je peux inclure ces entités dans le file XML.

Vous voulez dire inclure les définitions d'entité? Je pense que c'est une manière simple et robuste, si cela ne vous dérange pas de rendre le file XML un peu plus grand. Vous pourriez avoir un file «inclus» (find un sur le Web) qui est une entité externe, que vous faites reference en haut de votre file XML principal.

Un inconvénient est que l'parsingur XML que vous utilisez doit être celui qui traite des entités externes (ce que tous les parsingurs ne doivent pas faire). Et il doit résoudre correctement l'URL (éventuellement relative) de l'entité externe à quelque chose accessible. Ce n'est pas trop grave, mais cela peut augmenter les contraintes sur vos outils de traitement.

4 . Vous pouvez interdire le non-XML dans le contenu collé. Entre autres choses, cela interdit les references d'entités qui ne sont pas prédéfinies en XML (les 5 que Tomalak mentionne) ou définies dans le contenu lui-même. Toutefois, cela peut enfreindre les exigences de l'application, si les users doivent pouvoir coller HTML ici.

5 . Vous pouvez parsingr le contenu collé en tant que HTML dans un tree DOM en définissant some.Div.innerHTML = thePastedContent; En d'autres termes, créez un div quelque part (probablement affichage = aucun, sauf pour le debugging). Dites que vous avez alors une variable javascript myDiv qui détient cet élément div et une autre variable myField qui détient l'élément qui est votre champ de text d'input. Ensuite, en javascript, vous faites

 myDiv.innerHTML = myField.value; 

qui prend le text non corrigé de myField, l'parsing dans un tree HTML DOM et le colle dans myDiv en tant que contenu HTML.

Ensuite, vous utiliserez une méthode basée sur le browser pour la serialization (= "de-parsing") de l'tree DOM en XML. Voir par exemple cette question . Ensuite, vous envoyez le résultat au server en tant que XML.

Que vous souhaitiez faire ce correctif dans le browser ou sur le server (comme le suggère @Hannes) dépendra de la taille des données, de la rapidité avec laquelle la réponse doit être, de la qualité de votre server et de la security de l'envoi des pirates informatiques XML non bien formé à dessein.

Si vous voulez convertir tous les caharackers, cela peut vous aider (je l'ai écrit depuis un certain time:)

http://www.lautr.com/convert-all-applicable-characters-to-numeric-entities-for-use-in-xml

 function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); function _convertAlphaEntitysToNumericEntitys ($ entity) { function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); return '& #'. ord (html_entity_decode ($ entity [0])). ';'; function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); $ content = preg_replace_callback ( function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); '/ & ([\ w \ d] +); / i', function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); '_convertAlphaEntitysToNumericEntitys', function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); $ content); function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); function _convertAsciOver127toNumericEntitys ($ entity) { function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); if (($ asciCode = ord ($ entity [0]))> 127) function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); returnner '& #'. $ asciCode. ';'; function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); return $ entity [0]; function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); $ content = preg_replace_callback ( function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content); '/ [^ \ w \ d] / i', function _convertAlphaEntitysToNumericEntitys($entity) { return '&#'.ord(html_entity_decode($entity[0])).';'; } $content = preg_replace_callback( '/&([\w\d]+);/i', '_convertAlphaEntitysToNumericEntitys', $content); function _convertAsciOver127toNumericEntitys($entity) { if(($asciCode = ord($entity[0])) > 127) return '&#'.$asciCode.';'; else return $entity[0]; } $content = preg_replace_callback( '/[^\w\d ]/i', '_convertAsciOver127toNumericEntitys', $content);