Cosa sono i caratteri non validi in XML


229

Sto lavorando con alcuni XML che contengono stringhe come:

<node>This is a string</node>

Alcune delle stringhe che sto passando ai nodi avranno personaggi come &, #, $, ecc .:

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

Questo non è valido a causa di &.

Non posso avvolgere queste stringhe in CDATA in quanto devono essere come sono. Ho provato a cercare un elenco di caratteri che non possono essere inseriti in nodi XML senza essere in un CDATA.

Qualcuno può indicarmi la direzione di uno o fornirmi un elenco di personaggi illegali?


4
Qualche motivo valido per non usare CDATA?
Peter Perháč,

1
Sì, sto passando la stringa a un CMS chiamato Fatwire e il nodo con i dati non può essere in un CDATA, non sono sicuro del motivo per cui funziona Fatwire :(
RailsSon

@Peter: come posso usare CDATA nel mio caso? stackoverflow.com/questions/6906705/…
Radek,

Risposte:


147

I personaggi solo illegali &, <e >(così come "o 'negli attributi).

Stanno escape usando entità XML , in questo caso si desidera &amp;per &.

In realtà, però, dovresti usare uno strumento o una libreria che scriva XML per te e astratti questo genere di cose per te in modo da non doverti preoccupare.


82
Alcuni caratteri di controllo non sono ammessi. Vedi la mia risposta qui sotto.
dolmen,

43
In realtà non è del tutto vero. Un numero di caratteri ASCII inferiori non è valido. Se si tenta di scrivere 0x03 in un documento Xml, in genere si verifica un errore e se si riesce a sfuggire correttamente a un documento XML, la maggior parte degli utenti si lamenterà del carattere non valido. Edge case ma succede.
Rick Strahl,

16
Questa risposta è assolutamente sbagliata. Ecco la mia eccezione XML con il carattere illegale 0x12 'System.Xml.XmlException:' ', il valore esadecimale 0x12, è un carattere non valido'
George

8
È anche sbagliato nell'altra direzione; oltre a perdere ogni singolo personaggio illegale, i personaggi che sostiene siano illegali sono perfettamente legali, anche se con un significato speciale nel contesto.
Jon Hanna,

6
In XML 1.0 ci sono molti caratteri illegali. In effetti, anche l'uso di un'entità personaggio per la maggior parte dei personaggi di controllo causerà un errore durante l'analisi.
Thayne,

218

OK, separiamo la domanda dei personaggi che:

  1. non sono affatto validi in nessun documento XML.
  2. deve essere evaso.

La risposta fornita da @dolmen in " Cosa sono i caratteri non validi in XML " è ancora valida ma deve essere aggiornata con la specifica XML 1.1.

1. Caratteri non validi

I caratteri qui descritti sono tutti i caratteri che possono essere inseriti in un documento XML.

1.1. In XML 1.0

L'elenco globale dei caratteri consentiti è:

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

Fondamentalmente, i caratteri di controllo e i caratteri al di fuori degli intervalli Unicode non sono consentiti. Ciò significa anche che &#x3;è vietato chiamare ad esempio l'entità personaggio .

1.2. In XML 1.1

L'elenco globale dei caratteri consentiti è:

[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]

Questa revisione della raccomandazione XML ha esteso i caratteri consentiti in modo da consentire i caratteri di controllo e tiene conto di una nuova revisione dello standard Unicode, ma questi non sono ancora consentiti: NUL (x00) , xFFFE , xFFFF ...

Tuttavia, l'uso di caratteri di controllo e caratteri Unicode indefiniti è sconsigliato.

Si può anche notare che tutti i parser non tengono sempre conto di ciò e che i documenti XML con caratteri di controllo potrebbero essere respinti.

2. Personaggi che devono essere sfuggiti (per ottenere un documento ben formato):

Il <devono essere preceduti da un &lt;soggetto, in quanto si presume essere l'inizio di un tag.

Il &deve essere preceduti da un &amp;soggetto, poiché si presume essere l'inizio di un riferimento di entità

L' >dovrebbero essere preceduti da &gt;entità. Non è obbligatorio - dipende dal contesto - ma si consiglia vivamente di evitarlo.

L' 'dovrebbero essere preceduti da un &apos;ente - obbligatoria in attributi definiti tra virgolette semplici, ma è fortemente consigliato per sfuggire sempre.

L' "dovrebbero essere preceduti da un &quot;ente - obbligatoria in attributi definiti tra virgolette, ma è fortemente consigliato per sfuggire sempre.


171

L'elenco dei caratteri validi è nella specifica XML :

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

7
Dovresti notare che, sebbene siano caratteri legali, & < > " 'devono essere evitati in determinati contesti.
D. Shawley,

7
"Legale" in questo contesto significa che i loro valori decodificati finali sono legali, non legali nel flusso. Come sopra, alcuni valori legali devono essere salvati in-stream.
SilverbackNet,

Ho un problema in cui 0x1c è un personaggio illegale ... Alla ricerca di una possibilità in java come evitarli ....
basZero

Una bella panoramica di quali caratteri sono validi e quali non lo sono può essere trovata qui validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel,

8
@xamde Quell'elenco è carino, ma mostra solo i caratteri che possono essere usati per avviare un elemento XML. Il problema attuale è quali caratteri sono validi in un file XML in generale. Ci sono alcuni personaggi che non sono ammessi da nessuna parte.
Jon Senchyna,

59

Questo è un codice C # per rimuovere i caratteri XML non validi da una stringa e restituire una nuova stringa valida.

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, ""); 
}

6
Per Java, il modello regex sarebbe lo stesso. E quindi puoi usare il metodo chiamato replaceAll nella classe String che prevede un modello regex come parametro. Controlla questo: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca,

2
Ho caratteri non validi nella mia stringa: SUSITARIMO D & # x5; L DARBO SUTARTIES Questo codice non rimuove & # x5; Quindi il documento XML non riesce a essere avviato.
Dainius Kreivys,

Credo che non si possa semplicemente inserire questo modello in un costruttore di regex .NET. Non credo che riconosca \u10000e \u10FFFFsia caratteri singoli in quanto richiedono due charistanze utf-16 ciascuno, e secondo i documenti potrebbero non esserci più di 4 cifre. [\u10000-\u10FFFF]è più probabile analizzato come [ \u1000, 0-\u10FF, F, F] che è strano guardando, ma legale.
GSerg,


7

Oltre alla risposta di potame, se vuoi scappare usando un blocco CDATA.

Se inserisci il testo in un blocco CDATA, non è necessario utilizzare l'escaping . In tal caso è possibile utilizzare tutti i caratteri nel seguente intervallo :

rappresentazione grafica di possibili caratteri

Nota: Inoltre, non è consentito utilizzare la ]]>sequenza di caratteri. Perché corrisponderebbe alla fine del blocco CDATA.

Se ci sono ancora caratteri non validi (ad es. Caratteri di controllo), probabilmente è meglio usare un qualche tipo di codifica (ad es. Base64).


3
In un blocco CDATA o meno, alcuni caratteri sono vietati in XML.
dolmen,

4
esattamente, non è quello che ho scritto? quote: "tutti i caratteri nel seguente intervallo ". Con questo intendo solo i personaggi in questo intervallo specifico. Altri personaggi non sono ammessi. - pienamente d'accordo ; ma non capisco il downvote. - nessun sentimento duro però.
bvdb,

6

Un altro modo semplice per sfuggire ai caratteri XML / XHTML potenzialmente indesiderati in C # è:

WebUtility.HtmlEncode(stringWithStrangeChars)

Personaggi non validi
dolmen,

1
Ha scritto Xml non Html.
Emanuele,

6

Un altro modo per rimuovere caratteri XML errati in C # sta usando XmlConvert.IsXmlChar(Disponibile da .NET Framework 4.0)

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

oppure puoi verificare che tutti i caratteri siano validi per XML:

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

.Net Fiddle

Ad esempio, il simbolo della scheda verticale ( \v) non è valido per XML, è UTF-8 valido, ma non è XML 1.0 valido, e anche molte librerie (incluso libxml2) lo mancano e restituiscono silenziosamente XML non valido.


2

In sintesi, i caratteri validi nel testo sono:

  • tab, avanzamento riga e ritorno a capo.
  • tutti i caratteri non di controllo sono validi tranne & e <.
  • >non è valido se segue ]].

Le sezioni 2.2 e 2.4 della specifica XML forniscono la risposta in dettaglio:

Personaggi

I caratteri legali sono tab, ritorno a capo, avanzamento riga e caratteri legali di Unicode e ISO / IEC 10646

Dati del personaggio

Il carattere e commerciale (&) e la parentesi angolare sinistra (<) non devono apparire nella loro forma letterale, tranne quando utilizzati come delimitatori di markup o all'interno di un commento, un'istruzione di elaborazione o una sezione CDATA. Se sono necessari altrove, devono essere sottoposti a escape utilizzando rispettivamente i riferimenti ai caratteri numerici o le stringhe "&" e "<". La parentesi ad angolo retto (>) può essere rappresentata usando la stringa ">" e, per compatibilità, deve essere sfuggita usando ">" o un riferimento di carattere quando appare nella stringa "]]>" nel contenuto, quando quello stringa non segna la fine di una sezione CDATA.



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;

In C #, usa System.Security.SecurityElement.Escapeo System.Net.WebUtility.HtmlEncodeper sfuggire a questi personaggi illegali.

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;"

1

Per le persone Java, Apache ha una classe di utilità ( StringEscapeUtils) che ha un metodo helper escapeXmlche può essere usato per sfuggire ai caratteri in una stringa usando entità XML.


1

Nel processore XML Woodstox, i caratteri non validi sono classificati con questo codice:

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");

Fonte da qui


-1

Qualcuno ha provato questo System.Security.SecurityElement.Escape(yourstring)? Ciò sostituirà i caratteri XML non validi in una stringa con il loro equivalente valido.


-5

Per XSL (nei giorni davvero pigri) uso:

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

tradurre tutti i segni & che non sono stati compilati su amp; a quelli propri.

Abbiamo casi in cui l'input è in CDATA ma il sistema che utilizza l'XML non lo tiene in considerazione. È una soluzione sciatta, attenzione ...


8
Se è sciatto, è davvero necessario pubblicarlo qui?
dolmen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.