Apa karakter yang tidak valid dalam XML

229

Saya bekerja dengan beberapa XML yang memiliki string seperti:

<node>This is a string</node>

Beberapa string yang saya lewat ke kelenjar akan memiliki karakter seperti &, #, $, dll .:

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

Ini tidak valid karena &.

Saya tidak bisa membungkus string ini dalam CDATA karena mereka harus seperti apa adanya. Saya mencoba mencari daftar karakter yang tidak dapat dimasukkan ke dalam node XML tanpa menjadi CDATA.

Dapatkah seseorang mengarahkan saya ke arah orang lain atau memberi saya daftar karakter ilegal?

RailsSon
sumber
4
Adakah alasan yang sah untuk tidak menggunakan CDATA?
Peter Perháč
1
Ya, saya melewati string ke CMS yang disebut Fatwire dan node dengan data tidak dapat berada dalam CDATA, saya tidak yakin mengapa itu cara Fatwire bekerja :(
RailsSon
@ Peter: Bagaimana saya bisa menggunakan CDATA dalam kasus saya? stackoverflow.com/questions/6906705/…
Radek

Jawaban:

147

Karakter hanya ilegal yang &, <dan >(serta "atau 'dalam atribut).

Mereka lolos menggunakan entitas XML , dalam hal ini yang Anda inginkan &amp;untuk &.

Tapi sungguh, Anda harus menggunakan alat atau pustaka yang menulis XML untuk Anda dan abstrakkan hal semacam ini untuk Anda sehingga Anda tidak perlu khawatir tentang hal itu.

Welbog
sumber
82
Beberapa karakter kontrol juga tidak diperbolehkan. Lihat jawaban saya di bawah ini.
dolmen
43
Sebenarnya itu tidak sepenuhnya benar. Sejumlah karakter ascii yang lebih rendah juga tidak valid. Jika Anda mencoba menulis 0x03 ke dokumen Xml, Anda biasanya mendapatkan kesalahan dan jika Anda berhasil menghindarinya ke dalam dokumen XML, sebagian besar pemirsa akan mengeluh tentang karakter yang tidak valid. Kasus tepi tetapi itu terjadi.
Rick Strahl
16
Jawaban ini benar-benar salah. Berikut ini adalah pengecualian XML saya dengan 0x12 karakter ilegal 'System.Xml.XmlException:' ', nilai heksadesimal 0x12, adalah karakter yang tidak valid'
George
8
Itu juga salah di arah lain; serta kehilangan setiap karakter ilegal tunggal, karakter yang diklaimnya ilegal adalah legal, walaupun dengan makna khusus dalam konteksnya.
Jon Hanna
6
Dalam XML 1.0 ada banyak karakter ilegal. Bahkan menggunakan entitas karakter untuk sebagian besar karakter kontrol akan menyebabkan kesalahan saat parsing.
Thayne
218

OK, mari kita pisahkan pertanyaan dari karakter yang:

  1. sama sekali tidak valid dalam dokumen XML apa pun.
  2. perlu melarikan diri.

Jawaban yang diberikan oleh @dolmen dalam " Apa karakter yang tidak valid dalam XML " masih valid tetapi perlu diperbarui dengan spesifikasi XML 1.1.

1. Karakter tidak valid

Karakter yang dijelaskan di sini adalah semua karakter yang diizinkan untuk dimasukkan dalam dokumen XML.

1.1. Dalam XML 1.0

Daftar global dari karakter yang diperbolehkan adalah:

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

Pada dasarnya, karakter kontrol dan karakter di luar rentang Unicode tidak diperbolehkan. Ini juga berarti bahwa memanggil misalnya entitas karakter &#x3;dilarang.

1.2. Dalam XML 1.1

Daftar global dari karakter yang diperbolehkan adalah:

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

Revisi rekomendasi XML ini telah memperluas karakter yang diizinkan sehingga karakter kontrol diizinkan, dan memperhitungkan revisi baru standar Unicode, tetapi yang ini masih tidak diizinkan: NUL (x00) , xFFFE , xFFFF ...

Namun, penggunaan karakter kontrol dan karakter Unicode yang tidak ditentukan tidak disarankan.

Dapat juga diperhatikan bahwa semua parser tidak selalu mempertimbangkan hal ini dan dokumen XML dengan karakter kontrol dapat ditolak.

2. Karakter yang perlu melarikan diri (untuk mendapatkan dokumen yang terbentuk dengan baik):

The <harus melarikan diri dengan &lt;entitas, karena diasumsikan awal tag.

The &harus melarikan diri dengan &amp;entitas, karena diasumsikan awal referensi entitas

The >harus melarikan diri dengan &gt;entitas. Itu tidak wajib - tergantung pada konteksnya - tetapi sangat disarankan untuk menghindarinya.

The 'harus melarikan diri dengan &apos;entitas - wajib di atribut yang didefinisikan dalam tanda kutip tunggal tetapi sangat disarankan untuk selalu menghindarinya.

The "harus melarikan diri dengan &quot;entitas - wajib di atribut yang didefinisikan dalam tanda kutip ganda tapi sangat disarankan untuk selalu menghindarinya.

potame
sumber
171

Daftar karakter yang valid ada dalam spesifikasi XML :

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
dolmen
sumber
7
Anda harus mencatat bahwa meskipun mereka adalah karakter hukum, & < > " 'harus melarikan diri dalam konteks tertentu.
D.Shawley
7
"Legal" dalam konteks ini berarti bahwa nilai akhir yang didekodekan adalah legal, bukan bahwa mereka legal dalam stream. Seperti di atas, beberapa nilai hukum harus diloloskan dalam aliran.
SilverbackNet
Saya punya masalah di mana 0x1c adalah karakter ilegal ... Mencari kemungkinan di Jawa bagaimana menghindari ini ....
basZero
Gambaran bagus karakter mana yang valid dan mana yang tidak dapat ditemukan di sini validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel
8
@xamde Daftar itu bagus, tetapi hanya menunjukkan karakter yang dapat digunakan untuk memulai elemen XML. Masalah yang dihadapi adalah karakter mana yang valid dalam file XML secara umum. Ada karakter tertentu yang tidak diizinkan di mana pun.
Jon Senchyna
59

Ini adalah kode C # untuk menghapus karakter yang tidak valid XML dari string dan mengembalikan string yang valid baru.

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
sumber
6
Untuk Jawa, pola regex akan sama. Dan kemudian Anda bisa menggunakan metode yang disebut replaceAll di String kelas yang mengharapkan pola regex sebagai parameter. Lihat ini: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca
2
Saya memiliki karakter yang tidak valid di string saya: SUSITARIMO D & # x5; L DARBO SUTARTIES Kode ini tidak menghapus & # x5; Jadi dokumen xml gagal masuk.
Dainius Kreivys
Saya percaya Anda tidak bisa begitu saja meletakkan pola ini ke konstruktor .NET regex. Saya tidak berpikir itu mengenali \u10000dan \u10FFFFsebagai karakter tunggal karena mereka memerlukan dua charcontoh utf-16 masing-masing, dan menurut dokumen mungkin tidak ada lebih dari 4 digit. [\u10000-\u10FFFF]kemungkinan besar diuraikan sebagai [ \u1000, 0-\u10FF, F, F] yang aneh melihat tetapi hukum.
GSerg
17

Karakter yang telah diumumkan sebelumnya adalah:

& < > " '

Lihat " Apa karakter khusus dalam XML? " Untuk informasi lebih lanjut.

cgp
sumber
Salah. Ini semua tidak valid. Hanya & & <yang selalu tidak valid dalam teks.
rghome
7

Selain jawaban potame, jika Anda ingin melarikan diri menggunakan blok CDATA.

Jika Anda meletakkan teks Anda di blok CDATA maka Anda tidak perlu menggunakan pelolosan . Dalam hal ini, Anda dapat menggunakan semua karakter dalam rentang berikut :

representasi grafis dari karakter yang mungkin

Catatan: Selain itu, Anda tidak diizinkan menggunakan ]]>urutan karakter. Karena itu akan cocok dengan akhir blok CDATA.

Jika masih ada karakter yang tidak valid (mis. Karakter kontrol), maka mungkin lebih baik menggunakan semacam pengkodean (mis. Base64).

bvdb
sumber
3
Baik dalam blok CDATA atau tidak, beberapa karakter dilarang dalam XML.
dolmen
4
tepatnya, bukankah itu yang saya tulis? kutipan: "semua karakter dalam kisaran berikut ". Maksud saya, hanya karakter dalam rentang tertentu ini. Karakter lain tidak diperbolehkan. - sangat setuju ; tapi saya tidak mengerti downvote. - tidak ada perasaan keras sekalipun.
bvdb
6

Cara mudah lain untuk lolos dari karakter XML / XHTML yang mungkin tidak diinginkan di C # adalah:

WebUtility.HtmlEncode(stringWithStrangeChars)
tiands
sumber
Karakter tidak valid
dolmen
1
Dia menulis Xml bukan Html.
Emanuele
6

Cara lain untuk menghapus karakter XML yang salah di C # menggunakan XmlConvert.IsXmlChar(Tersedia sejak .NET Framework 4.0)

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

atau Anda dapat memeriksa bahwa semua karakter XML-valid:

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

.Net Fiddle

Misalnya, simbol tab vertikal ( \v) tidak valid untuk XML, itu valid UTF-8, tetapi tidak valid XML 1.0, dan bahkan banyak perpustakaan (termasuk libxml2) melewatkannya dan diam-diam menghasilkan XML yang tidak valid.

Alex Vazhev
sumber
2

Singkatnya, karakter yang valid dalam teks adalah:

  • tab, feed baris dan carriage-return.
  • semua karakter non-kontrol valid kecuali & dan <.
  • >tidak valid jika mengikuti ]].

Bagian 2.2 dan 2.4 dari spesifikasi XML memberikan jawaban secara terperinci:

Karakter

Karakter legal adalah tab, carriage return, line feed, dan karakter legal Unicode dan ISO / IEC 10646

Data karakter

Karakter ampersand (&) dan braket sudut kiri (<) tidak boleh muncul dalam bentuk literalnya, kecuali bila digunakan sebagai pembatas markup, atau dalam komentar, instruksi pemrosesan, atau bagian CDATA. Jika mereka diperlukan di tempat lain, mereka harus melarikan diri menggunakan referensi karakter numerik atau string "&" dan "<" masing-masing. Braket sudut kanan (>) dapat direpresentasikan menggunakan string ">", dan harus, untuk kompatibilitas, diloloskan dengan menggunakan ">" atau referensi karakter ketika muncul dalam string "]]>" dalam konten, ketika itu string tidak menandai akhir dari bagian CDATA.

rghome
sumber
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;

Di C #, gunakan System.Security.SecurityElement.Escapeatau System.Net.WebUtility.HtmlEncodeuntuk menghindari karakter ilegal ini.

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;"
cinta hidup
sumber
1

Untuk orang Jawa, Apache memiliki kelas utilitas ( StringEscapeUtils) yang memiliki metode pembantu escapeXmlyang dapat digunakan untuk melarikan diri karakter dalam string menggunakan entitas XML.

A Null Pointer
sumber
1

Dalam prosesor XML Woodstox, karakter yang tidak valid diklasifikasikan oleh kode ini:

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

Sumber dari sini

Jerome Saint-Yves
sumber
-1

Adakah yang mencoba ini System.Security.SecurityElement.Escape(yourstring)? Ini akan menggantikan karakter XML yang tidak valid dalam string dengan padanannya yang valid.

klaydze
sumber
-5

Untuk XSL (pada hari yang benar-benar malas) saya menggunakan:

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

untuk menerjemahkan semua & -signs yang tidak diikuti på amp; untuk yang tepat.

Kami memiliki kasus di mana input berada dalam CDATA tetapi sistem yang menggunakan XML tidak memperhitungkannya. Ini adalah perbaikan yang ceroboh, waspadalah ...

Samson Wiklund
sumber
8
Jika ceroboh, apakah benar-benar perlu mempostingnya di sini?
dolmen