C # में अमान्य XML वर्णों से बच


84

मेरे पास एक स्ट्रिंग है जिसमें अमान्य XML वर्ण हैं। मैं स्ट्रिंग को पार्स करने से पहले अवैध XML वर्णों से कैसे बच (या निकाल) सकता हूं?


2
क्या आप अधिक संदर्भ प्रदान कर सकते हैं? एक नमूना इनपुट और एक नमूना अपेक्षित आउटपुट। इसके अलावा आप आउटपुट के साथ क्या करना चाहते हैं।
डारिन दिमित्रोव

5
क्या आप XML लिख रहे हैं? या आप XML को पढ़ने की कोशिश कर रहे हैं जो वास्तव में XML नहीं है?
मार्क Gravell

3
एक XmlWriter का उपयोग करें, यह आपके लिए अमान्य वर्णों से बच जाएगा
थॉमस लेवेस्क

2
@alireza आप टिप्पणी में यहाँ अगर आप सवाल लोगों (अधिक जानकारी के लिए) आप पूछ रहे हैं का जवाब और अधिक उपयोगी जवाब मिल जाएगा ...
मार्क Gravell

मुझे माफ कर दो। मैं कुछ घंटों के लिए दूर था। कृपया उस प्रश्न को पढ़ें, जिसके कारण यह है: stackoverflow.com/questions/8330619/ ... आपको वहां आवश्यक सभी जानकारी मिल जाएगी
Alireza Noori

जवाबों:


113

अवैध XML वर्णों को हटाने के तरीके के रूप में मैं आपको XmlConvert.IsXmlChar विधि का उपयोग करने का सुझाव देता हूं । इसे .NET फ्रेमवर्क 4 के बाद से जोड़ा गया था और इसे सिल्वरलाइट में भी प्रस्तुत किया गया है। यहाँ छोटा सा नमूना है:

void Main() {
    string content = "\v\f\0";
    Console.WriteLine(IsValidXmlString(content)); // False

    content = RemoveInvalidXmlChars(content);
    Console.WriteLine(IsValidXmlString(content)); // True
}

static string RemoveInvalidXmlChars(string text) {
    var validXmlChars = text.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray();
    return new string(validXmlChars);
}

static bool IsValidXmlString(string text) {
    try {
        XmlConvert.VerifyXmlChars(text);
        return true;
    } catch {
        return false;
    }
}

और अवैध XML वर्णों से बचने के तरीके के रूप में मैं आपको XmlConvert.EncodeName विधि का उपयोग करने का सुझाव देता हूं । यहाँ छोटा सा नमूना है:

void Main() {
    const string content = "\v\f\0";
    Console.WriteLine(IsValidXmlString(content)); // False

    string encoded = XmlConvert.EncodeName(content);
    Console.WriteLine(IsValidXmlString(encoded)); // True

    string decoded = XmlConvert.DecodeName(encoded);
    Console.WriteLine(content == decoded); // True
}

static bool IsValidXmlString(string text) {
    try {
        XmlConvert.VerifyXmlChars(text);
        return true;
    } catch {
        return false;
    }
}

अद्यतन: यह उल्लेख किया जाना चाहिए कि एन्कोडिंग ऑपरेशन एक लंबाई के साथ एक स्ट्रिंग पैदा करता है जो स्रोत स्ट्रिंग की लंबाई से अधिक या बराबर है। यह महत्वपूर्ण हो सकता है जब आप डेटाबेस में एक एन्कोडेड स्ट्रिंग को एक स्ट्रिंग कॉलम में लंबाई सीमा के साथ संग्रहीत करते हैं और डेटा स्तंभ सीमा को फिट करने के लिए अपने ऐप में स्रोत स्ट्रिंग लंबाई को मान्य करते हैं।


XmlConvert.VerifyXmlCharsयदि अपवाद में अमान्य वर्ण हैं, तो यह अपवाद नहीं फेंकता है, यह अशक्त स्ट्रिंग लौटाता है (और यदि सभी निहित वर्ण मान्य हैं तो तर्क लौटाता है)। बस कोशिश करो return XmlConvert.VerifyXmlChars (text) != null
मैट एनराइट


3
@IgorKustov मेरा बुरा! रिटर्न वैल्यू डॉक्यूमेंट का विरोधाभास लगता है, मुझे पकड़ने के लिए धन्यवाद।
मैट एनराइट

3
XmlConvert.EncodeName का उपयोग न करने पर सावधानी बरतें यदि स्ट्रिंग XML मान के लिए है। एक्सएमएल नाम प्रतिबंध सख्त हैं तो एक्सएमएल मूल्य प्रतिबंध और नाम एन्कोडिंग अनावश्यक अप्रत्याशित पलायन को जन्म देगा।
डेविड बर्ग

1
@arik मेरा कोड केवल प्रदर्शन के उद्देश्य से कार्य करता है, परिवर्तन से पहले और बाद में XML स्ट्रिंग की स्थिति दिखाने के लिए। जाहिर है, आपके कोड में आपको इसे मान्य करने की आवश्यकता नहीं है।
इगोर कुस्तोव

67

SecurityElement.Escape का उपयोग करें

using System;
using System.Security;

class Sample {
  static void Main() {
    string text = "Escape characters : < > & \" \'";
    string xmlText = SecurityElement.Escape(text);
//output:
//Escape characters : &lt; &gt; &amp; &quot; &apos;
    Console.WriteLine(xmlText);
  }
}

11
यह नियंत्रण वर्णों से नहीं बचता (जैसे char 30)।
झिमडेन

19

यदि आप xml लिख रहे हैं, तो xml बनाने के लिए फ्रेमवर्क द्वारा प्रदान की गई कक्षाओं का उपयोग करें। आपको भागने या किसी भी चीज से परेशान नहीं होना पड़ेगा।

Console.Write(new XElement("Data", "< > &"));

उत्पादन करेगा

<Data>&lt; &gt; &amp;</Data>

यदि आपको किसी XML फ़ाइल को पढ़ने की आवश्यकता है जो विकृत है, तो नियमित अभिव्यक्ति का उपयोग करें । इसके बजाय, Html Agility Pack का उपयोग करें ।


अच्छा लगा। क्या आपके पास XmlElement का उपयोग करने वाले किसी व्यक्ति के लिए एक समान विधि है?
djdanlib

3
अपडेट: XmlElement की इनरटेक्स्ट प्रॉपर्टी सेट करना चीजों को सही तरीके से भागने के लिए प्रकट होता है। मेरे ही सवाल का जवाब दिया, हुज़्ज़ह!
djdanlib

तो आपका xml बन रहा है? पसंद है <Data>&</Data>?
पियरे-एलेन विगेंट

2
हां, बिल्कुल यही समस्या है।
एलिरेज़ा नूरी

2
यदि आपके तत्वों की सामग्री में बैकस्पेस (0x08), कई अन्य नियंत्रण वर्ण या सरोगेट कोड बिंदु जैसे अमान्य वर्ण हैं, तो भी आपको समस्याएँ हो सकती हैं।
जकुबिसन

6

आयरिशमैन द्वारा प्रदान किया गया RemoveInvalidXmlChars विधि सरोगेट वर्णों का समर्थन नहीं करता है। इसका परीक्षण करने के लिए, निम्नलिखित उदाहरण का उपयोग करें:

static void Main()
{
    const string content = "\v\U00010330";

    string newContent = RemoveInvalidXmlChars(content);

    Console.WriteLine(newContent);
}

यह एक खाली स्ट्रिंग देता है, लेकिन यह नहीं होना चाहिए! इसे "\ U00010330" लौटना चाहिए क्योंकि वर्ण U + 10330 एक वैध XML वर्ण है।

सरोगेट वर्णों का समर्थन करने के लिए, मैं निम्नलिखित विधि का उपयोग करने का सुझाव देता हूं:

public static string RemoveInvalidXmlChars(string text)
{
    if (string.IsNullOrEmpty(text))
        return text;

    int length = text.Length;
    StringBuilder stringBuilder = new StringBuilder(length);

    for (int i = 0; i < length; ++i)
    {
        if (XmlConvert.IsXmlChar(text[i]))
        {
            stringBuilder.Append(text[i]);
        }
        else if (i + 1 < length && XmlConvert.IsXmlSurrogatePair(text[i + 1], text[i]))
        {
            stringBuilder.Append(text[i]);
            stringBuilder.Append(text[i + 1]);
            ++i;
        }
    }

    return stringBuilder.ToString();
}

4

यहां उपरोक्त विधि RemoveInvalidXmlChars का एक अनुकूलित संस्करण है जो हर कॉल पर एक नया सरणी नहीं बनाता है, इस प्रकार जीसी को अनावश्यक रूप से तनावग्रस्त करता है:

public static string RemoveInvalidXmlChars(string text)
{
    if (text == null)
        return text;
    if (text.Length == 0)
        return text;

    // a bit complicated, but avoids memory usage if not necessary
    StringBuilder result = null;
    for (int i = 0; i < text.Length; i++)
    {
        var ch = text[i];
        if (XmlConvert.IsXmlChar(ch))
        {
            result?.Append(ch);
        }
        else if (result == null)
        {
            result = new StringBuilder();
            result.Append(text.Substring(0, i));
        }
    }

    if (result == null)
        return text; // no invalid xml chars detected - return original text
    else
        return result.ToString();

}

यह ?.वाक्य रचना क्या है ? लाइन में result?.Append(ch);?
जेबी मोनिका के साथ।


1
// Replace invalid characters with empty strings.
   Regex.Replace(inputString, @"[^\w\.@-]", ""); 

नियमित अभिव्यक्ति पैटर्न [^ \ w। @ -] किसी भी वर्ण से मेल खाता है जो एक शब्द चरित्र, एक अवधि, एक @ प्रतीक, या एक हाइफ़न नहीं है। एक शब्द चरित्र किसी भी अक्षर, दशमलव अंक या विराम चिह्न योजक जैसे अंडरस्कोर है। इस पैटर्न से मेल खाने वाला कोई भी अक्षर String.Empty द्वारा प्रतिस्थापित किया जाता है, जो कि प्रतिस्थापन पैटर्न द्वारा परिभाषित स्ट्रिंग है। उपयोगकर्ता इनपुट में अतिरिक्त वर्णों की अनुमति देने के लिए, उन पात्रों को नियमित अभिव्यक्ति पैटर्न में वर्ण वर्ग में जोड़ें। उदाहरण के लिए, नियमित अभिव्यक्ति पैटर्न [^ \ w। @ - \%] एक इनपुट प्रतीक में एक प्रतिशत प्रतीक और एक बैकस्लैश की भी अनुमति देता है।

Regex.Replace(inputString, @"[!@#$%_]", "");

इसे भी देखें:

XML नाम टैग से अमान्य वर्ण हटाना - RegEx C #

यहाँ वर्णों को निर्दिष्ट XML स्ट्रिंग से निकालने का एक कार्य है:

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace XMLUtils
{
    class Standards
    {
        /// <summary>
        /// Strips non-printable ascii characters 
        /// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
        /// Refer to http://www.w3.org/TR/2006/REC-xml-20060816/#charsets for XML 1.0
        /// </summary>
        /// <param name="content">contents</param>
        /// <param name="XMLVersion">XML Specification to use. Can be 1.0 or 1.1</param>
        private void StripIllegalXMLChars(string tmpContents, string XMLVersion)
        {    
            string pattern = String.Empty;
            switch (XMLVersion)
            {
                case "1.0":
                    pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|7F|8[0-46-9A-F]9[0-9A-F])";
                    break;
                case "1.1":
                    pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|[19][0-9A-F]|7F|8[0-46-9A-F]|0?[1-8BCEF])";
                    break;
                default:
                    throw new Exception("Error: Invalid XML Version!");
            }

            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
            if (regex.IsMatch(tmpContents))
            {
                tmpContents = regex.Replace(tmpContents, String.Empty);
            }
            tmpContents = string.Empty;
        }
    }
}

0
string XMLWriteStringWithoutIllegalCharacters(string UnfilteredString)
{
    if (UnfilteredString == null)
        return string.Empty;

    return XmlConvert.EncodeName(UnfilteredString);
}

string XMLReadStringWithoutIllegalCharacters(string FilteredString)
{
    if (UnfilteredString == null)
        return string.Empty;

    return XmlConvert.DecodeName(UnfilteredString);
}

यह सरल विधि अमान्य वर्णों को उसी मान से प्रतिस्थापित करती है लेकिन XML संदर्भ में स्वीकार की जाती है।


स्ट्रिंग का उपयोग करने के लिए XMLWriteStringWithoutIllegalCharacters (स्ट्रिंग UnfilteredString) लिखें।
स्ट्रिंग पढ़ने के लिए XMLReadStringWithoutIllegalCharacters (string FilteredString) का उपयोग करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.