XML'deki geçersiz karakterler nedir


229

Ben gibi dizeleri tutan bazı XML ile çalışıyorum:

<node>This is a string</node>

Ben düğümlerine geçen olduğumu dizeleri bazıları olacak karakterler gibi &, #, $, vb .:

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

Bu, nedeniyle geçerli değil &.

Bu dizeleri oldukları gibi olması gerektiği gibi CDATA içine saramıyorum. Bir CDATA olmadan XML düğümlerine konamaz karakterlerin bir listesini aramaya çalıştım.

Birisi beni birinin yönünde gösterebilir veya bana yasadışı karakterlerin bir listesini verebilir mi?


4
CDATA kullanmamanın geçerli bir nedeni var mı?
Peter Perháč

1
Evet, ben Fatwire adlı bir CMS dize geçiriyorum ve veri ile düğüm bir CDATA olamaz, ben Fatwire neden böyle olduğundan emin değilim :(
RailsSon

@Peter: CDATA'mı nasıl kullanabilirim? stackoverflow.com/questions/6906705/…
Radek

Yanıtlar:


147

Sadece yasadışı karakterler &, <ve >(aynı zamanda "ya 'özniteliklerde).

Onlar kullanarak kurtuldu olduğunuz XML girdileri istediğiniz bu durumda, &amp;için &.

Gerçekten de, sizin için XML yazan ve bu tür şeyleri sizin için soyutlayan bir araç veya kütüphane kullanmalısınız, böylece endişelenmenize gerek kalmaz.


82
Bazı kontrol karakterlerine de izin verilmez. Cevabımı aşağıda görebilirsiniz.
dolmen

43
Aslında bu pek doğru değil. Birkaç alt ascii karakteri de geçersizdir. Bir Xml belgesine 0x03 yazmaya çalışırsanız, genellikle bir hata alırsınız ve bir XML belgesine düzgün bir şekilde kaçmayı başarırsanız, çoğu izleyici geçersiz karakterden şikayet eder. Edge kasası ama oluyor.
Rick Strahl

16
Bu cevap kesinlikle yanlış. İşte 0x12 yasadışı karakteri 'System.Xml.XmlException:' ', onaltılık değer 0x12, geçersiz bir karakter olan XML istisnam'
George

8
Diğer yönde de yanlış; her yasadışı karakteri kaçırmanın yanı sıra, yasadışı olduğunu iddia ettiği karakterler, bağlamda özel bir anlamla da olsa, tamamen yasaldır.
Jon Hanna

6
XML 1.0'da birçok geçersiz karakter vardır. Aslında, çoğu kontrol karakteri için bir karakter varlığı kullanmak bile ayrıştırırken hataya neden olur.
Thayne

218

Tamam, şu karakterler sorununu ayıralım:

  1. hiçbir XML belgesinde hiç geçerli değildir.
  2. kaçmak gerekiyor.

@Dolmen tarafından "XML'de geçersiz karakterler nelerdir " bölümünde verilen yanıt hala geçerlidir, ancak XML 1.1 belirtimiyle güncellenmesi gerekir.

1. Geçersiz karakterler

Burada açıklanan karakterler, bir XML belgesine eklenmesine izin verilen tüm karakterlerdir.

1.1. XML 1.0'da

İzin verilen karakterlerin genel listesi:

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

Temel olarak, Unicode aralıklarının dışındaki kontrol karakterlerine ve karakterlere izin verilmez. Bu aynı zamanda, örneğin karakter varlığının çağrılmasının &#x3;yasak olduğu anlamına da gelir .

1.2. XML 1.1'de

İzin verilen karakterlerin genel listesi:

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

XML önerisinin bu revizyonu izin verilen karakterleri genişletti, bu yüzden kontrol karakterlerine izin verildi ve Unicode standardının yeni bir revizyonunu dikkate alıyor, ancak bunlara hala izin verilmiyor: NUL (x00) , xFFFE , xFFFF ...

Ancak, kontrol karakterleri ve tanımsız Unicode karakter kullanımı önerilmez.

Tüm ayrıştırıcıların bunu her zaman dikkate almadığı ve kontrol karakterlerine sahip XML belgelerinin reddedilebileceği de görülebilir.

2. Kaçması gereken karakterler (iyi biçimlendirilmiş bir belge elde etmek için):

<Bir öncelenmelidir &lt;bir etiketi başlangıcı olarak kabul edildiğinden, varlık.

&Bir öncelenmelidir &amp;o başlayan bir varlık referans olarak kabul edildiğinden, varlık

>İle kaçtı edilmelidir &gt;varlık. Zorunlu değildir - bağlama bağlıdır - ancak kaçması şiddetle tavsiye edilir.

'Bir ile kaçan edilmelidir &apos;varlık - tek tırnak içinde tanımlanmış özelliklerde bulunan zorunlu ama kuvvetle hep ondan kaçmak için tavsiye edilir.

"Bir ile kaçan edilmelidir &quot;varlık - çift tırnak içinde tanımlanmış özelliklerde bulunan zorunlu ama kuvvetle hep ondan kaçmak için tavsiye edilir.


171

Geçerli karakterlerin listesi XML spesifikasyonundadır :

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

7
Her ne kadar yasal karakterler olsalar da, & < > " 'belirli bağlamlarda kaçmaları gerektiğini unutmayın .
D.Shawley

7
Bu bağlamda "Yasal", dekode edilmiş nihai değerlerinin akışta yasal olduğu değil yasal olduğu anlamına gelir. Yukarıda olduğu gibi, bazı yasal değerlerin yayın içinde kaçması gerekir.
SilverbackNet

0x1c yasadışı bir karakter olduğu bir sorun var ... Java bu nasıl önlemek için bir olasılık arıyor ....
basZero

Hangi karakterlerin geçerli ve hangilerinin geçerli olmadığına dair güzel bir genel bakış burada bulunabilir availablechar.com/d/xml10/xml10_namestart
Dr. Max Völkel

8
@xamde Bu liste güzel, ancak yalnızca bir XML öğesini başlatmak için kullanılabilecek karakterleri gösteriyor. Eldeki sorun genel olarak bir XML dosyasında hangi karakterlerin geçerli olduğudur. Hiçbir yerde izin verilmeyen belirli karakterler var.
Jon Senchyna

59

Bu, bir dizeden XML geçersiz karakterlerini kaldırmak ve yeni bir geçerli dize döndürmek için bir C # kodudur.

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
Java için normal ifade kalıbı aynı olur. Ve sonra bir regex desenini parametre olarak bekleyen String dizesinde replaceAll adlı yöntemi kullanabilirsiniz. Bunu kontrol edin: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca

2
Dizemde böyle geçersiz karakterler var: SUSITARIMO D & # x5; L DARBO SUTARTIES Bu kod & # x5; Böylece xml belgesi başlatılamıyor.
Dainius Kreivys

Bu kalıbı bir .NET regex yapıcısına koyamayacağınıza inanıyorum. Her biri iki utf-16 örneği gerektirdiğinden tanıdığı \u10000ve \u10FFFFtek karakter olduğunu düşünmüyorum charve dokümanlara göre 4 basamaktan daha fazla olmayabilir. [\u10000-\u10FFFF]Büyük olasılıkla olarak ayrıştırılır [ \u1000, 0-\u10FF, F, F] tuhaf görünen ancak yasal olan.
GSerg


7

Buna ek olarak, bir CDATA bloğu kullanarak kaçmak istiyorsanız.

Metninizi bir CDATA bloğuna koyarsanız, kaçmayı kullanmanız gerekmez . Bu durumda , aşağıdaki aralıktaki tüm karakterleri kullanabilirsiniz :

olası karakterlerin grafik gösterimi

Not: Bunun da ötesinde, ]]>karakter dizisini kullanmanıza izin verilmez . Çünkü CDATA bloğunun sonu ile eşleşir.

Hala geçersiz karakterler (örn. Kontrol karakterleri) varsa, muhtemelen bir tür kodlama kullanmak daha iyidir (örneğin base64).


3
Bir CDATA bloğunda olsun ya da olmasın, XML'de bazı karakterler yasaklanmıştır.
dolmen

4
tam olarak yazdığım bu değil mi? alıntı: " aşağıdaki aralıktaki tüm karakterler ". Demek istediğim, sadece bu belirli aralıktaki karakterler. Diğer karakterlere izin verilmiyor. - Tamamen katılıyorum ; ama aşağı oyu anlamıyorum. - zor duygular yok.
bvdb

6

C # 'da potansiyel olarak istenmeyen XML / XHTML karakterlerinden kaçmanın bir diğer kolay yolu:

WebUtility.HtmlEncode(stringWithStrangeChars)

Geçersiz karakterler
dolmen

1
Html değil Xml yazdı.
Emanuele

6

C # 'da hatalı XML karakterlerini kaldırmanın başka bir yolu da XmlConvert.IsXmlChar(.NET Framework 4.0'dan beri kullanılabilir )

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

veya tüm karakterlerin XML için geçerli olup olmadığını kontrol edebilirsiniz:

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

Net Fiddle

Örneğin, dikey sekme sembolü ( \v) XML için geçerli değildir, geçerli UTF-8'dir, ancak geçerli XML 1.0 değildir ve hatta birçok kitaplık (libxml2 dahil) onu özler ve sessizce geçersiz XML çıktısı verir.


2

Özet olarak, metindeki geçerli karakterler:

  • sekmesi, satır besleme ve satır başı.
  • ve dışındaki tüm kontrol dışı karakterler geçerlidir .&<
  • >aşağıdaki durumlarda geçerli değildir ]].

XML spesifikasyonunun 2.2 ve 2.4 bölümleri cevabı ayrıntılı olarak sağlar:

Karakterler

Yasal karakterler sekme, satır başı, satır besleme ve Unicode ve ISO / IEC 10646'nın yasal karakterleri

Karakter verileri

Ve işareti karakteri (&) ve sol açılı ayraç (<), biçimlendirme sınırlayıcılar olarak veya bir yorum, işleme talimatı veya bir CDATA bölümü dahilinde kullanıldığı durumlar dışında, tam anlamıyla görünmemelidir. Başka bir yere ihtiyaç duyulursa, ya sayısal karakter referansları ya da sırasıyla "&" ve "<" dizeleri kullanılarak kaçılmalıdır. Sağ açılı ayraç (>) ">" dizesi kullanılarak temsil edilebilir ve uyumluluk için içerikte ">" veya "]]>" dizesinde göründüğünde bir karakter başvurusu kullanılarak kaçılmalıdır. dize bir CDATA bölümünün sonunu işaretlemiyor.



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;

C # 'da, bu geçersiz karakterlerden kaçmak için System.Security.SecurityElement.Escapeveya System.Net.WebUtility.HtmlEncodetuşlarını kullanın .

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

Java milletlerinde Apache, XML objeleri kullanarak bir dizedeki karakterlerden kaçmak için kullanılabilecek StringEscapeUtilsbir yardımcı yönteme sahip bir yardımcı program sınıfına ( ) sahiptir escapeXml.


1

Woodstox XML işlemcisinde geçersiz karakterler bu kodla sınıflandırılır:

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

Buradan kaynak


-1

Bunu deneyen var System.Security.SecurityElement.Escape(yourstring)mı? Bu, bir dizedeki geçersiz XML karakterlerini geçerli eşdeğerleriyle değiştirir.


-5

XSL için (gerçekten tembel günlerde) kullanıyorum:

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

follwed olmayan tüm & işaretlerini çevirmek; uygun olanlara.

Girişin CDATA'da olduğu ancak XML'yi kullanan sistemin girişi dikkate almadığı durumlarımız var. Özensiz bir düzeltme, dikkat et ...


8
Özensiz ise, buraya göndermek gerçekten gerekli mi?
dolmen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.