142 votes

Existe-t-il un moyen d'échapper à un élément de fin CDATA dans le langage XML ?

Je me demandais s'il existait un moyen d'échapper à un élément de fin de CDATA ( ]]> ) dans une section CDATA d'un document XML. Ou, plus généralement, s'il existe une séquence d'échappement à utiliser à l'intérieur d'une section CDATA (mais si elle existe, je suppose que cela n'aurait probablement de sens que d'échapper les tokens de début ou de fin, de toute façon).

En fait, il est possible d'avoir un jeton de début ou de fin intégré dans un CDATA et de demander à l'analyseur de ne pas l'interpréter, mais de le traiter comme une simple séquence de caractères.

Probablement, vous devriez simplement refactoriser votre structure xml ou votre code si vous vous retrouvez à essayer de faire cela, mais même si je travaille avec xml sur une base quotidienne depuis environ 3 ans et que je n'ai jamais eu ce problème, je me demandais si c'était possible. Juste par curiosité.

Edita:

A part l'utilisation de l'encodage html...

4 votes

Tout d'abord, je considère que la réponse est correcte, mais je note que rien n'empêche quelqu'un d'encoder > comme > au sein de CData afin d'assurer l'intégration des ]]> ne sera pas analysé comme un CDEnd. Cela signifie simplement que c'est inattendu et que & doit PREMIÈREMENT être encodée comme & afin que les données puissent être correctement décodées. Les utilisateurs du document doivent également savoir décoder ces données. Ce n'est pas inhabituel, car les CData ont notamment pour but de contenir un contenu qu'un consommateur spécifique sait comment traiter. On ne peut pas s'attendre à ce qu'un tel CData soit interprété correctement par un consommateur générique.

1 votes

@nix, CDATA fournit simplement un moyen explicite de déclarer le contenu d'un nœud de texte de manière à ce que les jetons de langue à l'intérieur (autres que ]]>) ne soient pas analysés. Il ne développe pas les références d'entités comme > pour cette raison, donc dans un bloc CDATA, cela signifie simplement ces quatre caractères, pas '>'. Pour mettre les choses en perspective : dans la spécification XML, tout le contenu textuel est appelé "cdata", et pas seulement ces séquences ("données de caractères"). Il ne s'agit pas non plus d'agents de consommation spécifiques. (Une telle chose existe cependant : les instructions de traitement (<?instruction cible?>).

0 votes

(Je dois ajouter que même si ce genre de choses va à l'encontre de l'intention originale du nœud, tout est juste dans la longue et tortueuse bataille avec XML. Je pense simplement qu'il pourrait être utile pour les lecteurs de savoir que < ![CDATA[]]> n'a pas été conçu dans ce but).

178voto

S.Lott Points 207588

Vous devez découper vos données en morceaux pour dissimuler les ]]> .

Voici le texte complet :

<![CDATA[]]]]><![CDATA[>]]>

Le premier <![CDATA[]]]]> a le ]] . Le deuxième <![CDATA[>]]> a le > .

1 votes

Merci pour votre réponse. Je cherchais plutôt quelque chose comme un équivalent de la barre oblique inverse (dans les chaînes de caractères en C, PHP, Java, etc.). D'après la règle citée par ddaa, il semble que cela n'existe pas.

32 votes

C'est la réponse qui devrait être acceptée. S'échapper est un terme légèrement ambigu, mais cette réponse aborde sans aucun doute l'esprit de la évasion . Dommage qu'elle ne corresponde pas à la conception étroite qu'a l'OP de la notion de évasion qui exige arbitrairement que le caractère backslash soit impliqué pour une raison quelconque.

0 votes

J'apprécie le fait de pouvoir "obtenir" cette réponse.

151voto

ddaa Points 19102

Il est clair que cette question est purement académique. Heureusement, elle a une réponse très précise.

Vous ne pouvez pas échapper à une séquence de fin CDATA. La règle de production 20 de la norme XML spécification est très claire :

[20]    CData      ::=      (Char* - (Char* ']]>' Char*))

EDIT : Cette règle de produit signifie littéralement "Une section CData peut contenir tout ce que vous voulez MAIS la séquence ']]>'. Il n'y a pas d'exception".

EDIT2 : Le même section lit également :

Dans une section CDATA, seule la chaîne CDEnd est reconnue comme une marque, de sorte que les crochets d'angle gauches et les esperluettes peuvent apparaître sous leur forme littérale ; ils n'ont pas besoin (et ne peuvent pas) être échappés à l'aide de ". &lt; " et " &amp; ". Les sections CDATA ne peuvent pas être imbriquées.

En d'autres termes, il n'est pas possible d'utiliser des références d'entités, des balises ou toute autre forme de syntaxe interprétée. Le seul texte analysé à l'intérieur d'une section CDATA est ]]> et il met fin à la section.

Il n'est donc pas possible d'échapper ]]> dans une section CDATA.

EDIT3 : Le même section lit également :

2.7 Sections CDATA

[Définition : Les sections CDATA peuvent se trouver partout où des données de caractère peuvent se trouver ; elles sont utilisées pour échapper à des blocs de texte contenant des caractères qui seraient autrement reconnus comme des balises. Les sections CDATA commencent par la chaîne "< ![CDATA[" et se terminent par la chaîne "]]>" :]

Ensuite, il peut y avoir une section CDATA partout où des données de caractère peuvent se trouver, y compris plusieurs sections CDATA adjacentes à la place d'une seule section CDATA. Il est ainsi possible de diviser le ]]> et placer ses deux parties dans des sections CDATA adjacentes.

ex :

<![CDATA[Certain tokens like ]]> can be difficult and <invalid>]]> 

doit s'écrire

<![CDATA[Certain tokens like ]]]]><![CDATA[> can be difficult and <valid>]]>

2 votes

En effet. Je ne suis pas un universitaire, mais comme je l'ai dit dans la question, je suis simplement curieux de savoir ce qu'il en est. Pour être honnête, je vous crois sur parole, car j'ai du mal à comprendre la syntaxe utilisée pour la règle. Merci pour votre réponse.

1 votes

Il se lit comme suit : Char* (l'ensemble de toutes les séquences de caractères) - (sauf) Char* ']]>' Char* (l'ensemble de toutes les séquences de caractères qui incluent la sous-chaîne ']]>').

0 votes

Merci pour cette précision supplémentaire. J'accepte votre réponse comme étant celle qui répond le mieux à la question que j'ai posée. (La réponse de S. Lott fournit une solution de contournement, ce qui est très bien, bien qu'elle ne traite pas spécifiquement d'un caractère ou d'une séquence d'échappement.

17voto

Jason Pyeron Points 356

Vous n'échappez pas à la ]]> mais vous échappez à la > après ]] en insérant ]]><![CDATA[ avant le > Il s'agit d'une sorte de \ en C/Java/PHP/Perl, mais seulement nécessaire avant une chaîne de caractères. > et après une ]] .

BTW,

La réponse de S.Lott est la même que celle-ci, mais elle est formulée différemment.

3 votes

Cette façon de dire les choses donne aux gens une fausse idée. Il s'agit d'une no s'échapper. ]]]]><![CDATA[> n'est pas une séquence magique pour ]]> . ]]]]> tiene ]] des caractères comme données, et ]]> met fin à la section CDATA en cours. <![CDATA[> commence une nouvelle section CDATA et place > en elle. Il s'agit en fait de deux éléments différents qui seront traités différemment lors de l'utilisation d'un analyseur DOM. Vous devez en être conscient. Cette façon de faire est similaire à ]]]><![CDATA[]> sauf qu'il met ] dans la première et ]> dans le deuxième CDATA. La différence demeure.

1 votes

La différence est exagérée, puisque le contenu CDATA est traité comme une portée littérale de texte échappé. Ce n'est que lorsqu'on joue avec le DOM que cela importe vraiment, et à ce niveau, on a de toute façon affaire à d'autres limites invisibles comme les nœuds de texte, de commentaire et d'instruction de traitement.

7voto

Robert Rossney Points 43767

S. Lott a raison : on n'encode pas la balise de fin, on la répartit sur plusieurs sections CDATA.

Comment rencontrer ce problème dans le monde réel : en utilisant un éditeur XML pour créer un document XML qui sera introduit dans un système de gestion de contenu, essayez d'écrire un article sur les sections CDATA. Votre astuce habituelle consistant à intégrer des échantillons de code dans une section CDATA ne fonctionnera pas ici. Vous pouvez imaginer comment j'ai appris cela.

Mais dans la plupart des cas, vous ne rencontrerez pas ce problème, et voici pourquoi : si vous voulez stocker (disons) le texte d'un document XML en tant que contenu d'un élément XML, vous utiliserez probablement une méthode DOM, par exemple :

XmlElement elm = doc.CreateElement("foo");
elm.InnerText = "<[CDATA[[Is this a problem?]]>";

Et le DOM échappe raisonnablement au < et au >, ce qui signifie que vous n'avez pas intégré par inadvertance une section CDATA dans votre document.

Oh, et ceci est intéressant :

XmlDocument doc = new XmlDocument();

XmlElement elm = doc.CreateElement("doc");
doc.AppendChild(elm);

string data = "<![[CDATA[This is an embedded CDATA section]]>";
XmlCDataSection cdata = doc.CreateCDataSection(data);
elm.AppendChild(cdata);

Il s'agit probablement d'une idéosyncrasie du DOM .NET, mais cela n'entraîne pas d'exception. L'exception est levée ici :

Console.Write(doc.OuterXml);

Je suppose que ce qui se passe sous le capot, c'est que le XmlDocument utilise un XmlWriter pour produire sa sortie, et que le XmlWriter vérifie que le document est bien formé au fur et à mesure qu'il écrit.

0 votes

Eh bien, j'avais un exemple presque "réel". J'ai l'habitude de charger du Xml à partir de Flash qui contient des balises html dans des sections CDATA. Avoir un moyen de s'en échapper pourrait être utile, je suppose. Mais de toute façon, dans ce cas, le contenu CDATA est généralement du XHTML valide, et donc le CDATA "extérieur" pourrait être évité.

2 votes

Les CDATA peuvent presque toujours être évités. Je constate que les personnes qui se débattent avec les CDATA ne comprennent souvent pas ce qu'elles essaient vraiment de faire et/ou comment la technologie qu'elles utilisent fonctionne réellement.

0 votes

Oh, je devrais également ajouter que la seule raison pour laquelle le CMS auquel je faisais allusion dans ma réponse utilisait des CDATA était que je l'avais écrit et que je n'avais pas compris ce que j'essayais réellement de faire et/ou comment la technologie fonctionnait. Je n'avais pas besoin d'utiliser CDATA.

3voto

Shawn Becker Points 11

Voici un autre cas dans lequel ]]> doit être échappé. Supposons que nous devions enregistrer un document HTML parfaitement valide dans un bloc CDATA d'un document XML et que la source HTML ait son propre bloc CDATA. Par exemple, il se trouve que la source HTML possède son propre bloc CDATA :

<htmlSource><![CDATA[ 
    ... html ...
    <script type="text/javascript">
        /* <![CDATA[ */
        -- some working javascript --
        /* ]]> */
    </script>
    ... html ...
]]></htmlSource>

le suffixe CDATA commenté doit être remplacé par :

        /* ]]]]><![CDATA[> *//

puisqu'un analyseur XML ne saura pas comment gérer les blocs de commentaires javascript

0 votes

Il ne s'agit pas d'un cas particulier. Il suffit de remplacer ]]> con ]]]]><![CDATA[> s'applique toujours ici. Le fait qu'il s'agisse de JavaScript ou de commentaires n'est pas important.

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