อักขระที่ไม่ถูกต้องใน XML คืออะไร


229

ฉันกำลังทำงานกับ XML บางอย่างที่เก็บสตริงเช่น:

<node>This is a string</node>

บางส่วนของสตริงที่ฉันผ่านไปยังโหนดจะมีตัวละครที่ชอบ&, #, $ฯลฯ .:

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

&นี้ไม่ถูกต้องเนื่องจาก

ฉันไม่สามารถรวมสตริงเหล่านี้ใน CDATA ได้ตามที่พวกเขาต้องการ ฉันพยายามค้นหารายการอักขระที่ไม่สามารถใส่ในโหนด XML โดยไม่ต้องอยู่ใน CDATA

ใครบางคนสามารถชี้ฉันในทิศทางเดียวหรือให้รายชื่อตัวละครผิดกฎหมายได้หรือไม่?


4
มีเหตุผลที่ถูกต้องสำหรับการไม่ใช้ CDATA หรือไม่
Peter Perháč

1
ใช่ฉันกำลังส่งสตริงไปยัง CMS ชื่อ Fatwire และโหนดที่มีข้อมูลไม่สามารถอยู่ใน CDATA ได้ฉันไม่แน่ใจว่าทำไมมันถึงเป็นวิธีที่ Fatwire ใช้งานได้ :(
RailsSon

@Peter: ฉันจะใช้ CDATA ในกรณีของฉันได้อย่างไร stackoverflow.com/questions/6906705/…
Radek

คำตอบ:


147

ตัวละครเท่านั้นที่ผิดกฎหมาย&, <และ>(เช่นเดียวกับ"หรือ'ในแอตทริบิวต์)

พวกเขากำลังหนีโดยใช้หน่วยงาน XMLในกรณีนี้คุณต้องการสำหรับ&amp;&

อย่างไรก็ตามที่จริงแล้วคุณควรใช้เครื่องมือหรือไลบรารีที่เขียน XML สำหรับคุณและสรุปสิ่งต่าง ๆ เหล่านี้ให้คุณเพื่อที่คุณจะได้ไม่ต้องกังวลกับมัน


82
ไม่อนุญาตให้ใช้อักขระควบคุมบางตัว ดูคำตอบของฉันด้านล่าง
dolmen

43
จริงๆแล้วมันไม่จริงเลย จำนวนอักขระ ASCII ที่ต่ำกว่านั้นไม่ถูกต้องเช่นกัน หากคุณพยายามเขียน 0x03 ไปยังเอกสาร Xml คุณจะได้รับข้อผิดพลาดโดยทั่วไปและหากคุณพยายามที่จะหลบหนีออกไปในเอกสาร XML ผู้ชมส่วนใหญ่จะบ่นเกี่ยวกับตัวละครที่ไม่ถูกต้อง กรณีขอบ แต่มันเกิดขึ้น
Rick Strahl

16
คำตอบนี้ผิดอย่างยิ่ง นี่คือข้อยกเว้น XML ของฉันด้วยอักขระผิดกฎหมาย 0x12 'System.Xml.XmlException:' ', ค่าเลขฐานสิบหก 0x12 เป็นอักขระที่ไม่ถูกต้อง'
George

8
มันก็ผิดไปอีกทางหนึ่ง ตัวละครที่มันอ้างว่าผิดกฎหมายนั้นถูกกฎหมายอย่างสมบูรณ์แม้ว่าจะมีความหมายพิเศษในบริบทก็ตาม
Jon Hanna

6
ใน XML 1.0 มีอักขระที่ผิดกฎหมายจำนวนมาก ในความเป็นจริงแม้แต่การใช้เอนทิตีอักขระสำหรับอักขระควบคุมส่วนใหญ่จะทำให้เกิดข้อผิดพลาดเมื่อแยกวิเคราะห์
Thayne

218

ตกลงเรามาแยกคำถามของตัวละครที่:

  1. ไม่ถูกต้องในเอกสาร XML ใด ๆ
  2. จำเป็นต้องหลบหนี

คำตอบที่ได้รับจาก @dolmen ใน " สิ่งที่เป็นอักขระที่ไม่ถูกต้องใน XML " ยังคงใช้ได้ แต่ต้องได้รับการอัปเดตด้วยข้อมูลจำเพาะ XML 1.1

1. อักขระไม่ถูกต้อง

อักขระที่อธิบายในที่นี้เป็นอักขระทั้งหมดที่ได้รับอนุญาตให้ใส่ในเอกสาร XML

1.1 ใน XML 1.0

รายการทั่วโลกของตัวละครที่ได้รับอนุญาตคือ:

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

โดยทั่วไปแล้วไม่อนุญาตให้ใช้อักขระควบคุมและอักขระนอกช่วง Unicode ซึ่งหมายความว่า&#x3;ห้ามมิให้มีการโทรหาตัวอย่างเช่น

1.2 ใน XML 1.1

รายการทั่วโลกของตัวละครที่ได้รับอนุญาตคือ:

[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 นี้ได้ขยายตัวอักขระที่ได้รับอนุญาตดังนั้นจึงอนุญาตให้ใช้อักขระควบคุมและพิจารณาการแก้ไขมาตรฐาน Unicode ใหม่ แต่ยังไม่อนุญาตให้ใช้เหล่านี้: NUL (x00) , xFFFE , xFFFF ...

อย่างไรก็ตามการใช้อักขระควบคุมและ Unicode char ที่ไม่ได้กำหนดนั้นไม่ได้รับการสนับสนุน

นอกจากนี้ยังสามารถสังเกตได้ว่าตัวแยกวิเคราะห์ทั้งหมดไม่ได้คำนึงถึงเรื่องนี้เสมอไปและเอกสาร XML ที่มีอักขระควบคุมอาจถูกปฏิเสธ

2. ตัวละครที่ต้องหลบหนี (เพื่อให้ได้เอกสารที่มีรูปแบบถูกต้อง):

<จะต้องหนีไปกับ&lt;นิติบุคคลเพราะมันจะถือว่าเป็นจุดเริ่มต้นของแท็กที่

&จะต้องหนีไปกับ&amp;นิติบุคคลเพราะมันจะถือว่าเป็นจุดเริ่มต้นการอ้างอิงนิติบุคคล

>ควรจะหนีไปกับ&gt;นิติบุคคล มันไม่ได้บังคับ - มันขึ้นอยู่กับบริบท - แต่ก็ควรที่จะหลีกเลี่ยง

'ควรจะหนีไปกับ&apos;นิติบุคคล - บังคับใช้ในแอตทริบิวต์ที่กำหนดไว้ในราคาเดียว แต่ก็ควรอย่างยิ่งที่จะหนีมันเสมอ

"ควรจะหนีไปกับ&quot;นิติบุคคล - บังคับใช้ในแอตทริบิวต์ที่กำหนดไว้ในคำพูดคู่ แต่ก็ควรอย่างยิ่งที่จะหนีมันเสมอ


171

รายการอักขระที่ถูกต้องอยู่ในข้อมูลจำเพาะ XML :

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

7
คุณควรทราบว่าถึงแม้ว่าพวกเขาจะเป็นตัวละครที่ถูกกฎหมาย แต่& < > " 'ก็ต้องหลบหนีในบริบทบางอย่าง
D.Shawley

7
"ถูกกฎหมาย" ในบริบทนี้หมายความว่าค่าถอดรหัสสุดท้ายของพวกเขานั้นถูกกฎหมายไม่ใช่ว่าถูกกฎหมายในสตรีม ดังกล่าวข้างต้นค่าทางกฎหมายบางอย่างจะต้องมีการหลบหนีในสตรีม
SilverbackNet

ผมมีปัญหาที่ 0x1c เป็นตัวละครที่ผิดกฎหมาย ... มองความเป็นไปได้ใน java หนึ่งวิธีการหลีกเลี่ยงเหล่านี้ ....
basZero

ภาพรวมที่ดีซึ่งตัวละครที่ถูกต้องและไม่สามารถหาได้ที่นี่validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel

8
@xamde รายการนั้นดี แต่จะแสดงเฉพาะอักขระที่อาจใช้ในการเริ่มองค์ประกอบ XML ปัญหาในมือคืออักขระที่ถูกต้องในไฟล์ XML โดยทั่วไป มีตัวละครบางตัวที่ไม่ได้รับอนุญาต
Jon Senchyna

59

นี่คือรหัส C # เพื่อลบอักขระ XML ที่ไม่ถูกต้องออกจากสตริงและส่งคืนสตริงที่ถูกต้องใหม่

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 รูปแบบ regex จะเหมือนกัน จากนั้นคุณสามารถใช้วิธีที่เรียกว่า replaceAll ในคลาส String ที่ต้องการรูปแบบ regex เป็นพารามิเตอร์ ตรวจสอบสิ่งนี้: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca

2
ฉันมีอักขระที่ไม่ถูกต้องในสตริงของฉัน: SUSITARIMO D & # x5; L DARBO SUTARTIES รหัสนี้ไม่ได้ลบ & # x5; ดังนั้นเอกสาร xml จึงไม่สามารถเริ่มต้นได้
Dainius Kreivys

ฉันเชื่อว่าคุณไม่สามารถใส่รูปแบบนี้เป็นตัวสร้าง. regex NET ฉันไม่คิดว่ามันจำได้\u10000และ\u10FFFFเป็นตัวอักษรเดียวเพราะพวกเขาต้องการสองcharอินสแตนซ์utf-16 แต่ละและตามเอกสารอาจจะไม่เกิน 4 หลัก [\u10000-\u10FFFF]จะแยกกันมากที่สุดน่าจะเป็น [ \u1000, 0-\u10FF, F, F] ซึ่งเป็นที่แปลก แต่มองทางกฎหมาย
GSerg

17

อักขระที่ประกาศไว้ล่วงหน้าคือ:

& < > " '

ดูที่ " อักขระพิเศษใน XML คืออะไร " สำหรับข้อมูลเพิ่มเติม


ไม่ถูกต้อง. สิ่งเหล่านี้ไม่ถูกต้องทั้งหมด มีเพียง & และ <เท่านั้นที่ไม่ถูกต้องในข้อความ
rghome

7

นอกจากคำตอบของ potame หากคุณต้องการหลบหนีโดยใช้บล็อก CDATA

หากคุณใส่ข้อความของคุณในบล็อก CDATA แล้วคุณไม่จำเป็นที่จะใช้หลบหนี ในกรณีนี้คุณสามารถใช้อักขระทั้งหมดในช่วงต่อไปนี้ :

การแสดงกราฟิกของตัวละครที่เป็นไปได้

หมายเหตุ: นอกจากนั้นคุณไม่ได้รับอนุญาตให้ใช้]]>ลำดับอักขระ เพราะมันจะตรงกับจุดสิ้นสุดของบล็อก CDATA

หากยังมีอักขระที่ไม่ถูกต้อง (เช่นอักขระควบคุม) อาจเป็นไปได้ที่จะใช้การเข้ารหัสบางประเภท (เช่น base64)


3
ไม่ว่าจะอยู่ในบล็อก CDATA หรือไม่ก็ตามห้ามใช้อักขระบางตัวใน XML
dolmen

4
ใช่นั่นไม่ใช่สิ่งที่ฉันเขียน อ้างถึง: "ตัวละครทั้งหมดในช่วงต่อไปนี้ " โดยที่ฉันหมายถึงเฉพาะตัวละครในช่วงที่เฉพาะเจาะจงนี้ ไม่อนุญาตให้ใช้อักขระอื่น - เห็นด้วยอย่างเต็มที่ ; แต่ฉันไม่เข้าใจ downvote - ไม่มีความรู้สึกยาก
bvdb

6

อีกวิธีที่ง่ายในการหลีกเลี่ยง Chars XML / XHTML ที่ไม่พึงประสงค์ใน C # คือ:

WebUtility.HtmlEncode(stringWithStrangeChars)

ตัวละครไม่ถูกต้อง
dolmen

1
เขาเขียน Xml ไม่ใช่ Html
Emanuele

6

อีกวิธีหนึ่งในการลบตัวอักษร XML ที่ไม่ถูกต้องใน C # กำลังใช้งานอยู่XmlConvert.IsXmlChar(มีให้ตั้งแต่. NET Framework 4.0)

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

หรือคุณอาจตรวจสอบว่าตัวละครทั้งหมดเป็น XML ที่ถูกต้อง:

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

.Net Fiddle

ตัวอย่างเช่นสัญลักษณ์แท็บแนวตั้ง ( \v) ไม่ถูกต้องสำหรับ XML มันเป็น UTF-8 ที่ถูกต้อง แต่ไม่ถูกต้อง XML 1.0 และแม้แต่ไลบรารีจำนวนมาก


2

โดยสรุปอักขระที่ถูกต้องในข้อความคือ:

  • แท็บ line-feed และ carriage-return
  • ทุกอักขระที่ไม่ใช่การควบคุมที่ถูกต้องยกเว้น และ&<
  • >]]ไม่ถูกต้องถ้าต่อไปนี้

ส่วนที่ 2.2 และ 2.4 ของข้อกำหนด XML ให้คำตอบโดยละเอียด:

ตัวละคร

อักขระทางกฎหมาย ได้แก่ แท็บการขึ้นบรรทัดใหม่การป้อนบรรทัดและอักขระที่ถูกกฎหมายของ Unicode และ ISO / IEC 10646

ข้อมูลตัวละคร

อักขระเครื่องหมายแอมเปอร์แซนด์ (&) และวงเล็บมุมซ้าย (<) ต้องไม่ปรากฏในรูปแบบตัวอักษรยกเว้นเมื่อใช้เป็นตัวคั่นมาร์กอัปหรือภายในความคิดเห็นคำสั่งการประมวลผลหรือส่วน CDATA หากจำเป็นต้องใช้ที่อื่นพวกเขาจะต้องหลบหนีโดยใช้การอ้างอิงอักขระตัวเลขหรือสตริง "&" และ "<" ตามลำดับ วงเล็บมุมขวา (>) อาจแสดงโดยใช้สตริง ">" และต้องใช้ความสามารถในการเข้ากันได้โดยใช้ ">" หรือการอ้างอิงอักขระเมื่อปรากฏในสตริง "]]>" ในเนื้อหาเมื่อ สตริงไม่ได้ทำเครื่องหมายจุดสิ้นสุดของส่วน 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;

ใน C # ใช้System.Security.SecurityElement.EscapeหรือSystem.Net.WebUtility.HtmlEncodeเพื่อหนีอักขระที่ผิดกฎหมายเหล่านี้

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 folks Apache มีคลาสยูทิลิตี้ ( StringEscapeUtils) ที่มีเมธอดตัวช่วยescapeXmlซึ่งสามารถใช้สำหรับการหลีกเลี่ยงอักขระในสตริงโดยใช้เอนทิตี XML


1

ในตัวประมวลผล Woodstox XML อักขระที่ไม่ถูกต้องถูกจัดประเภทตามรหัสนี้:

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

แหล่งที่มาจากที่นี่


-1

ใครเคยลองSystem.Security.SecurityElement.Escape(yourstring)บ้าง สิ่งนี้จะแทนที่อักขระ XML ที่ไม่ถูกต้องในสตริงด้วยค่าที่ถูกต้อง


-5

สำหรับ XSL (ในวันที่ขี้เกียจจริงๆ) ฉันใช้:

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

เพื่อแปล & -signs ทั้งหมดที่ไม่ใช่ follwed på amp; เพื่อคนที่เหมาะสม

เรามีกรณีที่อินพุตอยู่ใน CDATA แต่ระบบที่ใช้ XML นั้นไม่ได้คำนึงถึง มันเป็นการแก้ไขเลอะเทอะระวัง ...


8
หากมันเลอะเทอะจำเป็นต้องโพสต์ที่นี่จริงหรือ
dolmen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.