2011-11-24 19 views
13

.NET का XmlTextWriter अमान्य xml फ़ाइलों को बनाता है।XmlTextWriter गलत तरीके से नियंत्रण वर्ण लिख रहा है

एक्सएमएल में, कुछ नियंत्रण वर्णों को 'क्षैतिज टैब' (	) की अनुमति है, लेकिन अन्य 'लंबवत टैब' () की तरह नहीं हैं। (spec देखें।)

मेरे पास एक स्ट्रिंग है जिसमें एक यूटीएफ -8 नियंत्रण चरित्र है जिसे एक्सएमएल में अनुमति नहीं है।
हालांकि XmlTextWriter चरित्र से बच निकलता है, परिणामी एक्सएमएल अभी भी अमान्य है।

मैं कैसे सुनिश्चित कर सकता हूं कि XmlTextWriter कभी भी अवैध XML फ़ाइल नहीं बनाता है?

या, यदि XmlTextWriter के साथ ऐसा करना संभव नहीं है, तो मैं विशिष्ट नियंत्रण वर्णों को कैसे स्ट्रिप कर सकता हूं जिन्हें XML में स्ट्रिंग से अनुमति नहीं है?

उदाहरण कोड:

using (XmlTextWriter writer = 
    new XmlTextWriter("test.xml", Encoding.UTF8)) 
{ 
    writer.WriteStartDocument(); 
    writer.WriteStartElement("Test"); 
    writer.WriteValue("hello \xb world"); 
    writer.WriteEndElement(); 
    writer.WriteEndDocument(); 
} 

आउटपुट:

<?xml version="1.0" encoding="utf-8"?><Test>hello &#xB; world</Test> 
+0

आपके पास XML में एक बच निकला लंबवत टैब नहीं हो सकता है? क्या आप मानक का संदर्भ दे सकते हैं? – Jodrell

+0

@ जोडरेल यह सही है, आप नहीं कर सकते। एक्सएमएल पाठ के लिए है, न कि नियंत्रण वर्णों या बाइनरी डेटा के लिए। http://www.w3.org/TR/REC-xml/#charsets – jasso

उत्तर

10

एक व्यवहार का यह प्रलेखन documentation of the WriteString method में छिपा हुआ है, लेकिन यह लग रहा है यह पूरी कक्षा के लिए लागू होता है।

एक XmlWriter के डिफ़ॉल्ट व्यवहार को बनाएं उपयोग करके बनाए गए जब रेंज 0x-0x1F में चरित्र मूल्यों (छोड़कर सफेद स्थान पात्रों 0x9, 0xA, और 0xD) लिखने का प्रयास कर रहा एक ArgumentException फेंकने के लिए है। इन अमान्य XML वर्णों को XmlWriter बनाकर चेककैरक्टर्स प्रॉपर्टी को गलत पर सेट करके लिखा जा सकता है। ऐसा करने से अंकों को अंकीय वर्ण इकाइयों (&#0; &#0x1F के माध्यम से प्रतिस्थापित किया जा रहा है) में बदल दिया जाएगा। इसके अतिरिक्त, नए ऑपरेटर के साथ बनाया गया एक XmlTextWriter डिफ़ॉल्ट रूप से संख्यात्मक वर्ण इकाइयों के साथ अमान्य वर्णों को प्रतिस्थापित करेगा।

तो ऐसा लगता है कि आप अमान्य वर्ण लिखना समाप्त कर देते हैं क्योंकि आप XmlTextWriter क्लास का उपयोग कर रहे हैं। आपके लिए एक बेहतर समाधान XmlWriter Class का उपयोग करना होगा।

+0

यह थोड़ा अजीब है, लेकिन स्पष्ट रूप से 'XmlTextWriter' कन्स्ट्रक्टर मौजूद है, फिर भी आप इसका उपयोग नहीं करना चाहते हैं: http: // msdn। microsoft.com/en-us/library/kkz7cs0d.aspx –

1

SecurityElement.Escape जैसे .NET एस्केपर्स में निर्मित ठीक से बचें/इसे स्ट्रिप न करें।

  • आप दोनों लेखक और पाठक पर false करने के लिए CheckCharacters सेट कर सकते हैं यदि आपके आवेदन केवल एक फ़ाइल के साथ बातचीत है। परिणामी एक्सएमएल फ़ाइल अभी भी तकनीकी रूप से अमान्य होगी।

देखें:

XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); 
xmlWriterSettings.Encoding = new UTF8Encoding(false); 
xmlWriterSettings.CheckCharacters = false; 
var sb = new StringBuilder(); 
var w = XmlWriter.Create(sb, xmlWriterSettings); 
w.WriteStartDocument(); 
w.WriteStartElement("Test"); 
w.WriteString("hello \xb world"); 
w.WriteEndElement(); 
w.WriteEndDocument(); 
w.Close(); 
var xml = sb.ToString(); 
  • हैं स्थापित करने true को CheckCharacters (जो यह डिफ़ॉल्ट रूप से है) थोड़ा बहुत सख्त है, क्योंकि यह केवल एक अपवाद एक वैकल्पिक दृष्टिकोण है कि अमान्य XML को अधिक उदार है फेंक होगा पात्रों सिर्फ उन्हें पट्टी होगा:

Googling एक सा श्वेत सूची XmlTextEncoder झुकेंगे लेकिन यह भीहटा देंगेऔर अन्य श्रेणी में यू +007 एफ-यू +0084, यू +0086-यू + 00 9एफ कि विकिपीडिया पर Valid XML Characters के अनुसार केवल कुछ संदर्भों में मान्य हैं और आरएफसी ने निराश लेकिन अभी भी मान्य पात्रों के रूप में उल्लेख किया है।

public static class XmlTextExtentions 
{ 
    private static readonly Dictionary<char, string> textEntities = new Dictionary<char, string> { 
     { '&', "&amp;"}, { '<', "&lt;" }, { '>', "&gt;" }, 
     { '"', "&quot;" }, { '\'', "&apos;" } 
    }; 
    public static string ToValidXmlString(this string str) 
    { 
     var stripped = str 
      .Select((c,i) => new 
      { 
       c1 = c, 
       c2 = i + 1 < str.Length ? str[i+1]: default(char), 
       v = XmlConvert.IsXmlChar(c), 
       p = i + 1 < str.Length ? XmlConvert.IsXmlSurrogatePair(str[i + 1], c) : false, 
       pp = i > 0 ? XmlConvert.IsXmlSurrogatePair(c, str[i - 1]) : false 
      }) 
      .Aggregate("", (s, c) => {     
       if (c.pp) 
        return s; 
       if (textEntities.ContainsKey(c.c1)) 
        s += textEntities[c.c1]; 
       else if (c.v) 
        s += c.c1.ToString(); 
       else if (c.p) 
        s += c.c1.ToString() + c.c2.ToString(); 
       return s; 
      }); 
     return stripped; 
    } 
} 

यह एक यह पट्टी को उम्मीद है कि को छोड़कर सभी XmlTextEncoder परीक्षण गुजरता DEL जो XmlConvert.IsXmlChar, विकिपीडिया, और एक वैध (हालांकि हतोत्साहित) चरित्र के रूप में कल्पना के निशान।

3

बस इस सवाल जब मैं एक ही मुद्दे के साथ संघर्ष कर रहा था मिल गया और मैं एक regex के साथ इसे सुलझाने समाप्त हो गया:

return Regex.Replace(s, @"[\u0000-\u0008\u000B\u000C\u000E-\u001F]", ""); 

आशा है कि यह एक वैकल्पिक समाधान के रूप में किसी को मदद मिलती है।

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