2008-12-29 3 views
36

मान्य XML अक्षरों की सूची में अच्छी तरह से जाना जाता है, के रूप में कल्पना यह है द्वारा परिभाषित किया गया:यूनिकोड रेगेक्स; अमान्य XML वर्ण

#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] 

मेरा प्रश्न है या नहीं, यह इस बात के लिए एक PCRE नियमित अभिव्यक्ति बनाने के लिए संभव है (या इसके उलटा) यूनिकोड सामान्य श्रेणियों का उपयोग करके कोडपॉइंट्स को वास्तव में हार्ड कोडिंग किए बिना। एक उलटा कुछ [\ p {सीसी} \ p {सीएस} \ पी {सीएन}] जैसा हो सकता है, सिवाय इसके कि अनुचित रूप से लाइनफ़ीड्स और टैब को कवर करता है और कुछ अन्य अमान्य वर्णों को याद करता है।

उत्तर

6

प्रणाली है कि आंतरिक रूप से UTF-16 में कोड पॉइंट्स संग्रहीत करता है के लिए, यह 0xFFFF ऊपर और उन प्रणालियों में कोड पॉइंट्स के लिए किराए की जोड़े (xD800-xDFFF) उपयोग आम है यदि आप वास्तव में उदाहरण \ u12345 के लिए उपयोग कर सकते हैं या कि निर्दिष्ट करना होगा आप सत्यापित करना होगा एक सरोगेट जोड़ी के रूप में। (मुझे अभी पता चला है कि सी # में आप \u1234 (16 bit) and \U000(32-bit) का उपयोग कर सकते हैं)

Microsoft के अनुसार "डब्ल्यू 3 सी अनुशंसा सरोगेट वर्णों को तत्व या विशेषता नामों के अंदर अनुमति नहीं देती है।" W3s वेबसाइट खोजते समय मुझे C079 और C078 मिल गया जो कि ब्याज का हो सकता है।

+0

हालांकि यह एक उपयोगी कार्यान्वयन युक्ति है, यह वास्तव में मेरे प्रश्न का उत्तर नहीं देता है। आइए तर्कों के लिए मान लें कि कार्यान्वयन में गैर-बीएमपी पात्रों का प्रथम-दर समर्थन है, इसलिए सरोगेट पात्रों की आवश्यकता नहीं है। –

67

मैं जानता हूँ कि यह वास्तव में अपने प्रश्न का उत्तर नहीं है, लेकिन यह इसे यहाँ प्राप्त करने में उपयोगी है:

नियमित अभिव्यक्ति वैध एक्सएमएल वर्ण मैच के लिए:

[\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD] 

तो दूर करने के लिए एक्सएमएल से अवैध वर्ण, आप की तरह

// filters control characters but allows only properly-formed surrogate sequences 
private static Regex _invalidXMLChars = new Regex(
    @"(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\uFEFF\uFFFE\uFFFF]", 
    RegexOptions.Compiled); 

/// <summary> 
/// removes any unusual unicode characters that can't be encoded into XML 
/// </summary> 
public static string RemoveInvalidXMLChars(string text) 
{ 
    if (string.IsNullOrEmpty(text)) return ""; 
    return _invalidXMLChars.Replace(text, ""); 
} 

मैं था कुछ करना चाहते हैं हमारे निवासी रेगेक्स/एक्सएमएल प्रतिभा, he of the 4,400+ upvoted post, इसे जांचें, और उसने उस पर हस्ताक्षर किए।

+4

टेक्स्ट के बजाय। INNullOrEmpty() मुझे लगता है कि आपको स्ट्रिंग की आवश्यकता है। INNullOrEmpty (टेक्स्ट) –

+1

आप जेफ एटवुड हैं, आपको वास्तव में यहां अपनी सामग्री पर साइन इन करने के लिए किसी निवासी की आवश्यकता नहीं है। – jbnunn

+8

मैं अनुशंसा करता हूं कि अमान्य वर्णों को पट्टी न करें, बल्कि प्रतिस्थापन चरित्र (एफएफएफडी) के साथ उन्हें प्रतिस्थापित करें। अमान्य वर्णों को पट्टी करना डीबगिंग को कठिन बनाता है (समस्याएं अदृश्य हो जाती हैं) और कुछ मामलों में यह सुरक्षा छेद का कारण बन सकती है। –

4

मैं जावा में इस की कोशिश की और यह काम करता है:

private String filterContent(String content) { 
    return content.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", ""); 
} 

धन्यवाद जेफ।

+0

सुरुचिपूर्ण एक लाइन समाधान। धन्यवाद युवाल। – Dekel

1

उपरोक्त समाधान xml में हेक्स कोड मौजूद होने पर उपरोक्त समाधान मेरे लिए काम नहीं करते थे। जैसे

<element>&#x8;</element>

निम्नलिखित कोड टूट जाएगा:

string xmlFormat = "<element>{0}</element>"; 
string invalid = " &#x8;"; 
string xml = string.Format(xmlFormat, invalid); 
xml = Regex.Replace(xml, @"[\x01-\x08\x0B\x0C\x0E\x0F\u0000-\u0008\u000B\u000C\u000E-\u001F]", ""); 
XDocument.Parse(xml); 

यह रिटर्न:

XmlException: ', हेक्साडेसिमल मान 0x08, कोई अमान्य वर्ण है। लाइन 1, स्थिति 14।

निम्नलिखित सुधार regex जाता है और समस्या ऊपर उल्लेख निश्चित:

& #x ([0-8BCEFbcef] | 1 [0-9A-एफए च]); | [\ x01- \ x08 \ x0B \ x0C \ x0E \ x0F \ u0000- \ u0008 \ u000B \ u000C \ u000E- \ u001F]

यहाँ पहले 300 यूनिकोड वर्ण के लिए एक इकाई परीक्षण है और वह केवल पुष्टि करता है अमान्य वर्ण हटा दिए गए हैं:

[Fact] 
     public void validate_that_RemoveInvalidData_only_remove_all_invalid_data() 
     { 
      string xmlFormat = "<element>{0}</element>"; 
      string[] allAscii = (Enumerable.Range('\x1', 300).Select(x => ((char)x).ToString()).ToArray()); 
      string[] allAsciiInHexCode = (Enumerable.Range('\x1', 300).Select(x => "&#x" + (x).ToString("X") + ";").ToArray()); 
      string[] allAsciiInHexCodeLoweCase = (Enumerable.Range('\x1', 300).Select(x => "&#x" + (x).ToString("x") + ";").ToArray()); 

      bool hasParserError = false; 
      IXmlSanitizer sanitizer = new XmlSanitizer(); 

      foreach (var test in allAscii.Concat(allAsciiInHexCode).Concat(allAsciiInHexCodeLoweCase)) 
      { 
       bool shouldBeRemoved = false; 
       string xml = string.Format(xmlFormat, test); 
       try 
       { 
        XDocument.Parse(xml); 
        shouldBeRemoved = false; 
       } 
       catch (Exception e) 
       { 
        if (test != "<" && test != "&") //these char are taken care of automatically by my convertor so don't need to test. You might need to add these. 
        { 
         shouldBeRemoved = true; 
        } 
       } 
       int xmlCurrentLength = xml.Length; 
       int xmlLengthAfterSanitize = Regex.Replace(xml, @"&#x([0-8BCEF]|1[0-9A-F]);|[\u0000-\u0008\u000B\u000C\u000E-\u001F]", "").Length; 
       if ((shouldBeRemoved && xmlCurrentLength == xmlLengthAfterSanitize) //it wasn't properly Removed 
        ||(!shouldBeRemoved && xmlCurrentLength != xmlLengthAfterSanitize)) //it was removed but shouldn't have been 
       { 
        hasParserError = true; 
        Console.WriteLine(test + xml); 
       } 
      } 
      Assert.Equal(false, hasParserError); 
     } 
0

एक और तरीका है (.NET फ्रेमवर्क 4.0 के बाद से उपलब्ध है) XmlConvert.IsXmlChar Method उपयोग करने के साथ सी # में गलत एक्सएमएल वर्ण को दूर करने के

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

या आप जाँच कर सकते हैं कि सभी पात्रों एक्सएमएल-मान्य हैं।

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

नेट फिडल - https://dotnetfiddle.net/v1TNus

उदाहरण के लिए, ऊर्ध्वाधर टैब प्रतीक (\ v) नहीं एक्सएमएल के लिए मान्य है, यह वैध UTF-8, लेकिन मान्य नहीं XML 1.0, और यहां तक ​​कि कई पुस्तकालयों है (libxml2 सहित) इसे याद करें और चुपचाप अमान्य एक्सएमएल आउटपुट करें।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^