Je me demandais s'il existe un moyen d'échapper à un jeton de fin CDATA ( ]]>
) dans une section CDATA dans un document xml. Ou, plus généralement, s'il existe une séquence d'échappement à utiliser dans un CDATA (mais si elle existe, je suppose que cela n'aurait probablement de sens que d'échapper aux jetons de début ou de fin, de toute façon).
Fondamentalement, pouvez-vous avoir un jeton de début ou de fin incorporé dans un CDATA et dire à l'analyseur de ne pas l'interpréter mais de le traiter comme une autre séquence de caractères.
Probablement, vous devriez simplement refactoriser votre structure xml ou votre code si vous essayez de le faire, mais même si je travaille quotidiennement avec xml depuis environ 3 ans et que je n'ai jamais eu ce problème, Je me demandais si c'était possible. Juste par curiosité.
Éditer:
Autre que l'utilisation du codage html ...
>
comme>
dans CData pour garantir que intégré]]>
ne sera pas analysé comme CDEnd. Cela signifie simplement que c'est inattendu et que cela&
doit d'abord être encodé&
pour que les données puissent être correctement décodées. Les utilisateurs du document doivent également savoir décoder ce CData. Ce n'est pas rare car une partie de l'objectif de CData est de contenir du contenu qu'un consommateur spécifique comprend comment gérer. On ne peut pas s'attendre à ce qu'un tel CData soit interprété correctement par un consommateur générique.CDATA
été conçu pour autoriser tout : ils sont utilisés pour échapper des blocs de texte contenant des caractères qui seraient autrement reconnus comme du balisage Cela impliqueCDATA
aussi puisqu'il s'agit également de balisage. Mais, en fait, vous n'avez pas besoin du double encodage que j'impliquais.]]>
est un moyen acceptable de coder unCDEnd
dans unCDATA
.Réponses:
Clairement, cette question est purement académique. Heureusement, il 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 spécification XML est assez claire:
EDIT: Cette règle de produit signifie littéralement "Une section CData peut contenir tout ce que vous voulez MAIS la séquence ']]>'. Aucune exception.".
EDIT2: La même section lit également:
En d'autres termes, il n'est pas possible d'utiliser une référence d'entité, un balisage ou toute autre forme de syntaxe interprétée. Le seul texte analysé à l'intérieur d'une section CDATA est
]]>
, et il termine la section.Par conséquent, il n'est pas possible de s'échapper
]]>
dans une section CDATA.EDIT3: La même section lit également:
Ensuite, il peut y avoir une section CDATA partout où des données de caractères peuvent apparaître, y compris plusieurs sections CDATA adjacentes à la place d'une seule section CDATA. Cela permet de diviser le
]]>
jeton et de placer les deux parties de celui-ci dans des sections CDATA adjacentes.ex:
devrait être écrit comme
la source
<script>/*<![CDATA[*/javascript goes here/*]]>*/</script>
et mon javascript inclut juste cette séquence! J'aime l'idée de diviser en plusieurs sections CDATA ...[[United States dollar|US$]]>100 million (2013)
qui a été traduit[[United States dollar|US$]]>100 million (2013)
par le lecteur et l'écrivain a choisi d'utiliser CDATA pour échapper au texte et a échoué.Vous devez diviser vos données en morceaux pour masquer le fichier
]]>
.Voici le tout:
<![CDATA[]]]]><![CDATA[>]]>
Le premier
<![CDATA[]]]]>
a le]]
. Le second<![CDATA[>]]>
a le>
.la source
]]>
comme]]]]><![CDATA[>
. 5 fois la longueur ... wow. Mais alors, c'est une séquence peu commune.Vous n'échappez pas au
]]>
mais vous échappez à l'>
après]]
en insérant]]><![CDATA[
avant le>
, pensez à ceci comme une\
chaîne en C / Java / PHP / Perl mais nécessaire uniquement avant>
et après a]]
.BTW,
La réponse de S.Lott est la même que celle-ci, juste formulée différemment.
la source
]]]]><![CDATA[>
n'est pas une séquence magique pour]]>
.]]]]>
contient des]]
caractères comme données et]]>
termine la section CDATA actuelle.<![CDATA[>
démarre une nouvelle section CDATA et y met>
. Ce sont en fait deux éléments différents et seront traités différemment lorsque vous travaillez avec un analyseur DOM. Vous devez en être conscient. Cette façon de faire est similaire à]]]><![CDATA[]>
, sauf qu'elle met]
dans le premier et]>
dans le deuxième CDATA. La différence demeure.La réponse de S. Lott est juste: vous n'encodez pas la balise de fin, vous la divisez en plusieurs sections CDATA.
Comment résoudre 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 ordinaire consistant à intégrer des échantillons de code dans une section CDATA vous échouera ici. Vous pouvez imaginer comment j'ai appris cela.
Mais dans la plupart des cas, vous ne rencontrerez pas cela, et voici pourquoi: si vous voulez stocker (par exemple) le texte d'un document XML comme contenu d'un élément XML, vous utiliserez probablement une méthode DOM, par exemple:
Et le DOM échappe assez raisonnablement le <et le>, ce qui signifie que vous n'avez pas incorporé par inadvertance une section CDATA dans votre document.
Oh, et c'est intéressant:
C'est probablement une idéosyncrasie du DOM .NET, mais cela ne lève pas d'exception. L'exception est levée ici:
Je suppose que ce qui se passe sous le capot, c'est que le XmlDocument utilise un XmlWriter pour produire sa sortie, et le XmlWriter vérifie la bonne formation au fur et à mesure qu'il écrit.
la source
remplacez simplement
]]>
par]]]]><![CDATA[>
la source
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 possède son propre bloc CDATA. Par exemple:le suffixe CDATA commenté doit être changé en:
puisqu'un analyseur XML ne saura pas comment gérer les blocs de commentaires javascript
la source
]]>
par]]]]><![CDATA[>
s'applique toujours ici. Le fait que ce soit JavaScript ou commenté n'est pas important.En PHP:
'<![CDATA['.implode(explode(']]>', $string), ']]]]><![CDATA[>').']]>'
la source
Une manière plus propre en PHP:
N'oubliez pas d'utiliser un str_replace sécurisé multi-octets si nécessaire (non latin1
$string
):la source
Je ne pense pas que l'interruption de CDATA soit une bonne solution. Voici mon alternative ...
Utilisez
]
pour la séquence d'échappement suivie de la valeur hexadécimale de votre personnage. Comme dans le&#xhhhh;
=>]<unicode value>;
De cette façon, si vous essayez d'enregistrer
]]>
votre encodage fn produira]005D;]005D;]003E;
ce qui est ok dans CDATA.C'est mieux que de s'échapper par nom d'entité, car ceux-ci ne sont pas décodés à chaque fois dans votre application et vous pouvez avoir des priorités différentes pour échapper les entités avec esperluette vs échapper à d'autres caractères / séquences. En conséquence, vous avez plus de contrôle sur le contenu de CDATA.
la source
Voir cette structure:
Pour les balises CDATA internes, vous devez fermer avec
]]]]><![CDATA[>
au lieu de]]>
. Aussi simple que cela.la source