Quels sont les caractères invalides dans XML

229

Je travaille avec du XML qui contient des chaînes comme:

<node>This is a string</node>

Certaines des chaînes que je passe aux nœuds auront des personnages comme &, #, $, etc .:

<node>This is a string & so is this</node>

Ce n'est pas valable en raison de &.

Je ne peux pas envelopper ces chaînes dans CDATA car elles doivent être telles qu'elles sont. J'ai essayé de chercher une liste de caractères qui ne peuvent pas être mis dans des nœuds XML sans être dans un CDATA.

Quelqu'un peut-il m'orienter vers l'un ou me fournir une liste de personnages illégaux?

RailsSon
la source
4
Une raison valable pour ne pas utiliser CDATA?
Peter Perháč, le
1
Oui, je passe la chaîne à un CMS appelé Fatwire et le nœud avec les données ne peut pas être dans un CDATA, je ne sais pas pourquoi c'est la façon dont Fatwire fonctionne :(
RailsSon
@Peter: Comment puis-je utiliser CDATA dans mon cas? stackoverflow.com/questions/6906705/…
Radek

Réponses:

147

Les seuls caractères illégaux sont &, <et >(ainsi que "ou 'dans les attributs).

Ils échappèrent à l' aide des entités XML , dans ce cas , vous voulez &amp;pour &.

Vraiment, cependant, vous devriez utiliser un outil ou une bibliothèque qui écrit du XML pour vous et résume ce genre de chose pour vous afin que vous n'ayez pas à vous en soucier.

Welbog
la source
82
Certains caractères de contrôle ne sont pas non plus autorisés. Voir ma réponse ci-dessous.
dolmen
43
En fait, ce n'est pas tout à fait vrai. Un certain nombre de caractères ascii inférieurs sont également invalides. Si vous essayez d'écrire 0x03 dans un document Xml, vous obtenez généralement une erreur et si vous parvenez à l'échapper correctement dans un document XML, la plupart des utilisateurs se plaindront du caractère non valide. Affaire Edge mais ça arrive.
Rick Strahl
16
Cette réponse est absolument fausse. Voici mon exception XML avec le caractère illégal 0x12 'System.Xml.XmlException:' ', la valeur hexadécimale 0x12, est un caractère non valide'
George
8
C'est également faux dans l'autre sens; en plus de manquer chaque caractère illégal, les caractères qu'il prétend être illégaux sont parfaitement légaux, bien qu'avec une signification particulière dans le contexte.
Jon Hanna
6
Dans XML 1.0, il existe de nombreux caractères illégaux. En fait, même l'utilisation d'une entité de caractère pour la plupart des caractères de contrôle provoquera une erreur lors de l'analyse.
Thayne
218

OK, séparons la question des personnages qui:

  1. ne sont pas du tout valides dans aucun document XML.
  2. doivent être échappés.

La réponse fournie par @dolmen dans " Quels sont les caractères non valides dans XML " est toujours valide mais doit être mise à jour avec la spécification XML 1.1.

1. Caractères non valides

Les caractères décrits ici sont tous les caractères autorisés à être insérés dans un document XML.

1.1. En XML 1.0

La liste globale des caractères autorisés est:

[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

Fondamentalement, les caractères de contrôle et les caractères hors des plages Unicode ne sont pas autorisés. Cela signifie également que l'appel par exemple de l'entité caractère &#x3;est interdit.

1.2. Dans XML 1.1

La liste globale des caractères autorisés est:

[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]

Cette révision de la recommandation XML a étendu les caractères autorisés afin que les caractères de contrôle soient autorisés, et prend en compte une nouvelle révision de la norme Unicode, mais celles-ci ne sont toujours pas autorisées: NUL (x00) , xFFFE , xFFFF ...

Cependant, l'utilisation de caractères de contrôle et de caractères Unicode non définis est déconseillée.

On peut également remarquer que tous les analyseurs ne prennent pas toujours cela en compte et les documents XML avec des caractères de contrôle peuvent être rejetés.

2. Caractères à échapper (pour obtenir un document bien formé):

Le <doit être échappé avec une &lt;entité, car il est supposé être le début d'une balise.

Le &doit être échappé avec une &amp;entité, car il est supposé être le début d'une référence d'entité

Le >doit être échappé avec l' &gt;entité. Ce n'est pas obligatoire - cela dépend du contexte - mais il est fortement conseillé d'y échapper.

Le 'doit être échappé avec une &apos;entité - obligatoire dans les attributs définis entre guillemets simples mais il est fortement conseillé de toujours l'échapper.

Le "devrait être échappé avec une &quot;entité - obligatoire dans les attributs définis entre guillemets, mais il est fortement conseillé de toujours l'échapper.

potame
la source
171

La liste des caractères valides se trouve dans la spécification XML :

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
dolmen
la source
7
Vous devez noter que bien qu'ils soient des caractères légaux, & < > " 'ils doivent être échappés dans certains contextes.
D.Shawley
7
«Légal» dans ce contexte signifie que leurs valeurs finales décodées sont légales, et non pas légales dans le flux. Comme ci-dessus, certaines valeurs légales doivent être échappées dans le flux.
SilverbackNet
J'ai un problème où 0x1c est un caractère illégal ... Vous cherchez une possibilité en java comment les éviter ....
basZero
Un bon aperçu des caractères valides et qui ne le sont pas peut être trouvé ici validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel
8
@xamde Cette liste est intéressante, mais elle ne montre que les caractères qui peuvent être utilisés pour démarrer un élément XML. Le problème est de savoir quels caractères sont valides dans un fichier XML en général. Certains caractères ne sont autorisés nulle part.
Jon Senchyna
59

Il s'agit d'un code C # pour supprimer les caractères non valides XML d'une chaîne et renvoyer une nouvelle chaîne valide.

public static string CleanInvalidXmlChars(string text) 
{ 
    // From xml spec valid chars: 
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]     
    // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. 
    string re = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]"; 
    return Regex.Replace(text, re, ""); 
}
mathifonseca
la source
6
Pour Java, le modèle d'expression régulière serait le même. Et puis vous pouvez utiliser la méthode appelée replaceAll dans la classe String qui attend un modèle d'expression régulière en tant que paramètre. Vérifiez ceci: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca
2
J'ai des caractères non valides dans ma chaîne: SUSITARIMO D & # x5; L DARBO SUTARTIES Ce code ne supprime pas & # x5; Ainsi, le document xml ne parvient pas à init.
Dainius Kreivys
Je crois que vous ne pouvez pas simplement mettre ce modèle dans un constructeur de regex .NET. Je ne pense pas qu'il reconnaisse \u10000et en \u10FFFFtant que caractères uniques car ils nécessitent deux charinstances utf-16 chacun, et selon les documents, il pourrait ne pas y avoir plus de 4 chiffres. [\u10000-\u10FFFF]est très probablement analysé comme [ \u1000, 0-\u10FF, F, F] qui est bizarre, mais juridique.
GSerg
7

En plus de la réponse de potame, si vous voulez vous échapper en utilisant un bloc CDATA.

Si vous placez votre texte dans un bloc CDATA, vous n'avez pas besoin d'utiliser d'échappement . Dans ce cas, vous pouvez utiliser tous les caractères de la plage suivante :

représentation graphique des caractères possibles

Remarque: En plus de cela, vous n'êtes pas autorisé à utiliser la ]]>séquence de caractères. Parce qu'il correspondrait à la fin du bloc CDATA.

S'il y a encore des caractères invalides (par exemple des caractères de contrôle), alors il est probablement préférable d'utiliser une sorte de codage (par exemple base64).

bvdb
la source
3
Que ce soit dans un bloc CDATA ou non, certains caractères sont interdits en XML.
dolmen
4
n'est-ce pas exactement ce que j'ai écrit? citation: "tous les caractères de la plage suivante ". J'entends par là que seuls les personnages de cette gamme spécifique. Les autres personnages ne sont pas autorisés. - entièrement d'accord ; mais je ne comprends pas le downvote. - pas de rancune cependant.
bvdb
6

Un autre moyen simple d'échapper aux caractères XML / XHTML potentiellement indésirables en C # est:

WebUtility.HtmlEncode(stringWithStrangeChars)
tiands
la source
Caractères non valides
dolmen
1
Il a écrit Xml et non Html.
Emanuele
6

Une autre façon de supprimer les caractères XML incorrects en C # est d'utiliser XmlConvert.IsXmlChar(Disponible depuis .NET Framework 4.0)

public static string RemoveInvalidXmlChars(string content)
{
   return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());
}

ou vous pouvez vérifier que tous les caractères sont valides pour XML:

public static bool CheckValidXmlChars(string content)
{
   return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));
}

.Net Fiddle

Par exemple, le symbole de tabulation verticale ( \v) n'est pas valide pour XML, il est UTF-8 valide, mais pas XML 1.0 valide, et même de nombreuses bibliothèques (y compris libxml2) le manquent et produisent silencieusement du XML invalide.

Alex Vazhev
la source
2

En résumé, les caractères valides dans le texte sont:

  • tabulation, saut de ligne et retour chariot.
  • tous les caractères non contrôlés sont valides sauf & et <.
  • >n'est pas valide s'il suit ]].

Les sections 2.2 et 2.4 de la spécification XML fournissent la réponse en détail:

Personnages

Les caractères légaux sont tabulation, retour chariot, saut de ligne et les caractères légaux d'Unicode et ISO / IEC 10646

Données de caractère

Le caractère esperluette (&) et le crochet angulaire gauche (<) ne doivent pas apparaître dans leur forme littérale, sauf lorsqu'ils sont utilisés comme délimiteurs de balisage, ou dans un commentaire, une instruction de traitement ou une section CDATA. S'ils sont nécessaires ailleurs, ils doivent être échappés à l'aide de références de caractères numériques ou des chaînes "&" et "<" respectivement. La parenthèse à angle droit (>) peut être représentée à l'aide de la chaîne ">" et doit, pour des raisons de compatibilité, être échappée à l'aide de ">" ou d'une référence de caractère lorsqu'elle apparaît dans la chaîne "]]>" dans le contenu, lorsque cela la chaîne ne marque pas la fin d'une section CDATA.

rghome
la source
1
ampersand (&) is escaped to &amp;

double quotes (") are escaped to &quot;

single quotes (') are escaped to &apos; 

less than (<) is escaped to &lt; 

greater than (>) is escaped to &gt;

En C #, utilisez System.Security.SecurityElement.Escapeou System.Net.WebUtility.HtmlEncodepour échapper à ces caractères illégaux.

string xml = "<node>it's my \"node\" & i like it 0x12 x09 x0A  0x09 0x0A <node>";
string encodedXml1 = System.Security.SecurityElement.Escape(xml);
string encodedXml2= System.Net.WebUtility.HtmlEncode(xml);


encodedXml1
"&lt;node&gt;it&apos;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

encodedXml2
"&lt;node&gt;it&#39;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"
l'amour en direct
la source
1

Pour les gens Java, Apache a une classe utilitaire ( StringEscapeUtils) qui a une méthode d'assistance escapeXmlqui peut être utilisée pour échapper des caractères dans une chaîne à l'aide d'entités XML.

Un pointeur nul
la source
1

Dans le processeur XML Woodstox, les caractères non valides sont classés par ce code:

if (c == 0) {
    throw new IOException("Invalid null character in text to output");
}
if (c < ' ' || (c >= 0x7F && c <= 0x9F)) {
    String msg = "Invalid white space character (0x" + Integer.toHexString(c) + ") in text to output";
    if (mXml11) {
        msg += " (can only be output using character entity)";
    }
    throw new IOException(msg);
}
if (c > 0x10FFFF) {
    throw new IOException("Illegal unicode character point (0x" + Integer.toHexString(c) + ") to output; max is 0x10FFFF as per RFC");
}
/*
 * Surrogate pair in non-quotable (not text or attribute value) content, and non-unicode encoding (ISO-8859-x,
 * Ascii)?
 */
if (c >= SURR1_FIRST && c <= SURR2_LAST) {
    throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content");
}
throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output");

Source d' ici

Jérôme Saint-Yves
la source
-1

Quelqu'un a essayé ça System.Security.SecurityElement.Escape(yourstring)? Cela remplacera les caractères XML non valides dans une chaîne par leur équivalent valide.

klaydze
la source
-5

Pour XSL (les jours vraiment paresseux) j'utilise:

capture="&amp;(?!amp;)" capturereplace="&amp;amp;"

pour traduire tous les signes & qui ne sont pas suivis på amp; aux bons.

Nous avons des cas où l'entrée est en CDATA mais le système qui utilise le XML n'en tient pas compte. C'est une solution bâclée, méfiez-vous ...

Samson Wiklund
la source
8
Si c'est bâclé, est-il vraiment nécessaire de le poster ici?
dolmen