Aller au contenu | Aller au menu | Aller à la recherche

La section CDATA en Xml

Un internaute, ayant lu l'article Bien valider ses formulaires avec Javascript sur openweb, m'a demandé plus d'explications sur ce <![CDATA[ ...]]> que j'ai mis pour encadrer le code javascript...

En fait, cette notation fait tout simplement partie de la syntaxe XML. Elle permet de dire, au programme qui va analyser le fichier XML, de ne pas analyser / interpreter ce qu'il y a entre le <![CDATA[ et le ]]>. Attention : cela ne veut pas dire que le programme doit ignorer le contenu de la section. L'analyseur syntaxique va seulement le récupérer, sans chercher à repérer des balises, des entités ou tout autre spécificité syntaxique XML. La balise qui contient ce type de section a donc un contenu à l'identique de ce qu'il y a dans la section.

En effet, si on n'utilise pas <![CDATA[, et que le contenu a des caractères tels que le < ou le > par exemple, on est obligé de les transformer en entité &lt; ou &gt; (comme le & qui doit être &amp;). C'est plutôt galère à écrire, surtout si il s'agit de script javascript, où il faudrait donc transformer les opérateurs de comparaison "supérieur" et "inférieur" etc..

Le tag CDATA permet donc d'eviter ceci. Il est trés utile notament lorsqu'on veut indiquer un source XML dans un fichier XML. Par exemple, si on veut afficher ceci dans une page XHTML :

Voici comment afficher un menu en XUL :

 <menubar id="sample-menubar">
   <menu id="file-menu" label="Fichier">
      <menupopup id="file-popup">
        <menuitem label="Nouveau"/>
        <menuitem label="Ouvrir"/>
     </menupopup>
   </menu>
 </menubar>

En html, nous sommes obligés de transformer chaque < et > en entité. En XHTML, non. Il suffit de mettre le code source entre <![CDATA[ et le ]]>.

Mais ce n'est que de la théorie. En effet, en pratique, cela ne fonctionne pas avec IE (cela aurait été trop beau). Par contre cela fonctionne parfaitement avec Mozilla, quand la page XHTML est envoyé avec le type mime application/xhtml+xml.

On ne peut donc hélas pas utiliser les sections CDATA. Eh bien pour les scripts javascripts on n'a qu'à utiliser les commentaires <!-- et -->, me diriez vous. Oui mais non. Car en XML un commentaire est un commentaire. Son contenu doit être totalement ignoré par l'analyseur XML, il ne doit pas faire parti du contenu de la balise où il y a le commentaire. Ce qui est aisément vérifiable avec Mozilla : faites un test en lui envoyant une page XHTML avec le type mime application/xhtml+xml et une balise script comme ceci :

<script type="text/javascript"> <!--
      alert('hello');
   --></script>

Vous ne verrez jamais la petite boîte d'alerte avec le message Hello. Par contre, avec IE, vous la verrez. Mais ce n'est pas normal. Comme beaucoup de choses, Internet Explorer ne sait pas bien traiter les pages XHTML. C'est le boulet du web du début du 21ième siècle.

On pourrait enlever les balises de commentaires, mais là Mozilla s'insurge si il y a par exemple un < ou > qui traîne sans être transformé en entité. Et si on les transforme en entité, c'est IE qui n'est pas content car pour lui, une entité dans du code javascript, ce n'est pas normal (alors que Mozilla, un peu plus intelligent, interprète d'abord les entités avant d'exécuter le code).

Dans une page XHTML respectant les standards, les seules solutions comme je l'ai écrit à la fin de l'article, sont  :

  1. Mettre le script javascript dans un fichier à part, et faire un simple <script type="text/javascript" src="monscript.js"></script>
  2. Ou pour les masochistes, écrire le code entre ces deux bizarreries :
    <script type="text/javascript" >
    <!--/*--><![CDATA[//><!--
      ...
    //--><!]]>
    </script>

Commentaires

1. Le mercredi, avril 7 2004, 00:09 par rhésus

D'ailleurs, je crois savoir que le type mime correct pour un fichier javascript est "application/x-javascript" et pas "text/javascript", mais que internet explorer (encore lui) ne le gère pas...

2. Le mercredi, avril 7 2004, 09:19 par Greg

Pas trouvé de type mime pour javascript sur le site Iana http://www.iana.org/assignments/media-types/index.html Mais on peut lire sur la page d'accueil "RFC2045,RFC2046 specifies that Content Types, Content Subtypes, Character Sets, Access Types, and conversion values for MIME mail will be assigned and listed by the IANA."

Les types MIME ne seraient valables que pour les doc attachés aux mails ?

Sur la spec HTML 4.0 on parle de Content Type, pas de type MIME et on parle bien de text/javascript. Il n'y aurait pas une différence entre type MIME et Content Type ?

Laurent? Ganf? Karl? au secours... J'suis un poil perdu là :-D

3. Le mercredi, avril 7 2004, 09:54 par LaurentJ

Greg : oui alors là, j'avoue que tu met en lumière une question que je ne m'étais jamais posé. Et à vrai dire, je ne sais pas quoi répondre :-/

4. Le mercredi, avril 7 2004, 10:07 par Greg

D'un aut' côté, c'est pas vital non plus hein...

Mais depuis peu, j'aime bien COMPRENDRE : Faire des choses sans comprendre comment ça marche c'est malTM

En fait c'est surtout s'exposer à des problèmes par la suite.

5. Le mercredi, avril 7 2004, 11:15 par Ganf

Les types mime ont été réutilisés pour pas mal d'autres choses. On les retrouve même dans les explorateurs de fichiers modernes pour associer des applications à des types de fichier.

Il s'agit simplement d'un bon exemple de réutilisation où on n'a pas réinventé la roue mais où on a utiliser des déclarations et conventions qui existaient déjà. Content-type, mime-type, media-type, tout ça c'est plus ou moins du pareil au même. Personnellement j'utilise l'un ou l'autre presque indifférement (mais peut être ai-je tort).

Pour le coup du CDATA j'ai une autre solution à proposer (j'avoue, elle n'est pas de moi ... et je n'ai pas testé) :

<script type="text/javascript" >
// <![CDATA[ 
...
//]]>
</script>

cas 1 : les CDATA ne sont pas interprêtés, ils sont en commentaire "une ligne" et ne sont pas vu par le js, tout va bien

cas 2 : les CDATA sont interprétés, ils le sont avant le js, on aura simplement une ligne de commentaire vide en haut et en bas du code js, aucun dommage

cas 3 : les CDATA *et* le navigateur ne connait pas la balise <script>. Effectivement, là ça pose problème, mais vous en connaissez beaucoup des navigateurs qui ne connaissent pas la balise <script> ? je ne parle pas de ceux qui ne l'intêprêtent pas, je parle de ceux qui ne savent pas ce que c'est et risquent d'en afficher le contenu. Franchement, ça fait pas mal d'années que les commentaires de masquage du code js ne sont plus nécessaire (maintenant on masque les CDATA, l'histoire se répète ;))

Elle n'est pas plus simple ma syntaxe ?

6. Le mercredi, avril 7 2004, 15:43 par Greg

ganf> les types mime ont été réutilisés...

Merci Ganf pour ton explication.

Perso je les utilise pour rajouter des icones après mes liens vers des docs PDF ZIP... grâce à :after de CSS

Très pratique

7. Le lundi, avril 12 2004, 01:28 par Nicolas Krebs

(Ganf écrivit : ) « Les types mime ont été réutilisés pour pas mal d'autres choses. On les retrouve même dans les explorateurs de fichiers modernes pour associer des applications à des types de fichier.

Il s'agit simplement d'un bon exemple de réutilisation où on n'a pas réinventé la roue mais où on a utiliser des déclarations et conventions qui existaient déjà. Content-type, mime-type, media-type, tout ça c'est plus ou moins du pareil au même. Personnellement j'utilise l'un ou l'autre presque indifférement (mais peut être ai-je tort). » (Ganf).

Cela me semble vrai. Quelques compléments : http://www.cybercodeur.net/weblog/commentaires/detailsCarnet.php?idmessage=822 et avant dernier paragraphe de http://groups.google.com/groups?selm=bu0oh4$fc5$1@reader1.imaginet.fr&q=mime

8. Le samedi, mai 22 2004, 02:08 par ken

Pour envoyer une requête, insérant un mot ou une expression au milieu d'une URL, à un moteur de recherche.

Une boîte de dialogue pop-up s'ouvre pour demander la saisie des termes à rechercher, si aucune sélection n'a été faite auparavant.

Ainsi la nouvelle ligne ne sera pas désactivée en cas de non-sélection préalable.

Les variables sont, en plus de l'URL et du titre de la ligne du menu, l'id unique et le nom de la fonction (le choisir sans espace ni caractère spécial).

Le code suivant doit être ajouté dans qlookup.js (dossier <install>/chrome/qlookup/content/), avant le commentaire final :

// ============== function doGoogleAdvanced() { var selection = getSelection(); if (selection.length < 1) selection = prompt('Entrez les termes de la recherche',''); if (selection.length < 1) return; urlPrefix = 'http://www.google.com/search?as_q='; urlPostfix = '&num=100&hl=en&ie=ISO-8859-1&btnG=Google+Search&as_epq=&as_oq=&as_eq=&lr=&as_ft=i&as_filetype= &as_qdr=all&as_occt=any&as_dt=i&as_sitesearch=&safe=images'; doUrl(urlPrefix + selection + urlPostfix); } // ==============

Dans qlookup.xul (dossier <install>/chrome/qlookup/content/), avant la balise fermante </popup> ajouter la ligne de code suivante :

<menuitem id="qlookup-adv" label="Google Advanced" oncommand="doGoogleAdvanced()"/>

9. Le mardi, juin 29 2004, 11:11 par Grégoire

Mettre le script javascript dans un fichier à part, et faire un simple <script type="text/javascript" src="monscript.js"></script>

Intéressant article, mais personnellement j'ai du JavaScript dans une boucle PHP, donc mon code JavaScript est dynamique. Concrètement, c'est le code dans l'interface de SPIP que j'ai repris, quand on clique sur un petit triangle, on a un DIV qui se "déplie", et ce DIV est écrit en JavaScript. Son attribut "id" vaut "Layer1", "Layer2", etc, et je génère le chiffre avec PHP. Puis-je utiliser un fichier JavaScript externe?

Merci d'avance. Grégoire

10. Le mardi, juin 29 2004, 14:16 par LaurentJ

Oui tu peux utiliser un fichier javascript externe. il suffit que ton fichier javascript soit un fichier php :

<script type="text/javascript" src="monscript_js.php"></script>

Dans monscript_js.php tu as du php qui génère le script à la volée. tout simplement.

Par contre, il y a des moyens plus cool que de génerer du html en javascript. Tes divs devraient être en dur dans tes pages. Car si javascript désactivé ou n'est pas interprété (dans les navigateurs, dans les lecteurs vocaux d'écrans, les robots d'indexation comme google etc..) : le contenu de tes divs n'est pas lisible.

11. Le mardi, juin 29 2004, 14:54 par Grégoire

Merci pour ta réponse, je vais tester en mettant une variable statique dans le fichier PHP.

Je n'aime pas non plus le fait de générer des divs avec "document.write", mais c'est fait comme ça dans Spip et comme il y a une balise <noscript>, ça marche même si le JavaScript est désactivé : <noscript><div id="Layer$i" style="display:block;" /></noscript>

Cela dit, j'ai lu qu'en XHTML, "document.write" était obsolète, qu'il fallait ajouter des noeuds au document, XML oblige... Connais-tu la fonction qui permet de faire ça?

Re-merci d'avance. ;-) Grégoire

12. Le mardi, juin 29 2004, 16:07 par Grégoire

Après test, ça ne marche pas, la valeur de $i dans mon fichier mon_script_js.php, qui est initialisée à 1, vaut toujours 1 pour les autres appels. Du coup tous les divs ont le même id. Tout ça est logique, chaque appel à "mon_script_js.php" est fait par le navigateur au moment où il affiche la page. Pour le serveur, ce sont des requêtes qui n'ont aucun rapport les unes avec les autres, donc la variable statique est détruite et recréée à chaque fois.

Bref il faudrait que le W3 nous ponde un JavaScript reformulé en XML, car actuellement je ne vois pas comment on peut générer des JavaScripts donc certains morceaux sont calculés par PHP. Je vais donc servir mes pages en text/html, ou bien je vais me passer de cet effet visuel pour pouvoir garder le application/xhtml+xml. Dans les deux cas c'est pas cool. Mais merci quand même. :-)

Grégoire

13. Le mardi, juin 29 2004, 16:22 par LaurentJ

J'ai oublié de dire : le mon_script_js.php n'étant pas inclus par un include php, c'est donc considéré par PHP comme étant une page indépendante. Ce qui veut dire que tout ce qui est fait dans la page php qui a la balise script ne peut être réutilisé dans mon_script_js.php. Ce qui veut donc dire également qu'il faut dans ce script_js.php refaire les requêtes sql etc...

Cela veut dire aussi que si tu as des paramètres à la page de ton article (numero de l'article en l'occurance), il va falloir aussi le passer à ton script js pour qu'il fasse les bonnes requêtes. ex :

<script type="text/javascript" src="monscript_js.php?art_id=toto&amp;autre_param=..."></script>

Pour adapter tout ça à spip, certainement que ce n'est pas super évident à faire...

14. Le mardi, juin 29 2004, 17:25 par Grégoire

Oui en effet, je viens de me souvenir qu'on pouvait passer des variables par $_GET, à force de faire des formulaires j'avais oublié! Maintenant ça marche, mais pour ne pas utiliser document.write (qui ne marche pas en application/xhtml+xml), j'ai dû mettre ceci dans mon fichier inclus:

$i = $_GET['i'];
echo "        vis['$i'] = 'cacher';\n";
echo "        var element_div = document.getElementById(\"Layer$i\");\n";
echo "        element_div.style.display = 'none';\n";

Il est bien ton blog, j'y reviendrai! :-)

Grégoire