आप XmlSerializer का उपयोग करके CDATA के रूप में एक स्ट्रिंग को कैसे अनुक्रमित करते हैं?


90

क्या .नेट XmlSerializer का उपयोग करके CDATA के रूप में किसी स्ट्रिंग को क्रमबद्ध करना किसी विशेषता के माध्यम से संभव है?


2
दो उत्तरों के बारे में एक बात ध्यान देने योग्य है कि आपको CDataContentकेवल XML पढ़ने की आवश्यकता नहीं है । XmlSerializer.Deserializeस्वचालित रूप से आपके लिए इसे पाठ में बदल देगा।
क्रिस एस

जवाबों:


62
[XmlRoot("root")]
public class Sample1Xml
{
    internal Sample1Xml()
    {
    }

    [XmlElement("node")]
    public NodeType Node { get; set; }

    #region Nested type: NodeType

    public class NodeType
    {
        [XmlAttribute("attr1")]
        public string Attr1 { get; set; }

        [XmlAttribute("attr2")]
        public string Attr2 { get; set; }

        [XmlIgnore]
        public string Content { get; set; }

        [XmlText]
        public XmlNode[] CDataContent
        {
            get
            {
                var dummy = new XmlDocument();
                return new XmlNode[] {dummy.CreateCDataSection(Content)};
            }
            set
            {
                if (value == null)
                {
                    Content = null;
                    return;
                }

                if (value.Length != 1)
                {
                    throw new InvalidOperationException(
                        String.Format(
                            "Invalid array length {0}", value.Length));
                }

                Content = value[0].Value;
            }
        }
    }

    #endregion
}

8
मेरे लिए यह सबसे सुरुचिपूर्ण समाधान नहीं लगता है। क्या ऐसा करने का यह एकमात्र संभव तरीका है?
jamesaharvey

1
मुझे लगता है कि इसे पूरा करने का एकमात्र तरीका है, मैंने इस विषय को कहीं और देखा है और हमेशा एक ही उत्तर। फिलिप से उदाहरण थोड़ा साफ है, लेकिन एक ही अवधारणा है। केवल दूसरा तरीका जो मुझे पता है, वह है कि आप अपने स्वयं के <a href=" msdn.microsoft.com/en-us/library/…> को उस वर्ग पर लागू करें जो CDATA सामग्री का प्रतिनिधित्व करता है।
csharptest.net

मैं एक ही काम करना चाहता था क्योंकि ऐसा लगता है कि स्ट्रिंग को स्टोर करना जैसा कि सीडीएटीए प्रसंस्करण समय को कम करता है, जैसा कि इसके साथ हम केवल 'रीड / राइट स्ट्रिंग' है। XmlDocument / XmlCDataSection उदाहरणों को शामिल करना कितना महंगा है?
15

और पूरी विशेषता यह है कि हम क्रमिक तर्क विवरणों से डोमेन मॉडल कक्षाओं को साफ रखने में सक्षम हैं। अगर यह गंदा रास्ता ही एकमात्र रास्ता है तो यह बहुत दुखद है।
15

2
पृष्ठ के नीचे फिलिप का समाधान थोड़ा दूर है, ऐसा करने के लिए एक कठिन बात है।
कार्ल १

99
[Serializable]
public class MyClass
{
    public MyClass() { }

    [XmlIgnore]
    public string MyString { get; set; }
    [XmlElement("MyString")]
    public System.Xml.XmlCDataSection MyStringCDATA
    {
        get
        {
            return new System.Xml.XmlDocument().CreateCDataSection(MyString);
        }
        set
        {
            MyString = value.Value;
        }
    }
}

उपयोग:

MyClass mc = new MyClass();
mc.MyString = "<test>Hello World</test>";
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
StringWriter writer = new StringWriter();
serializer.Serialize(writer, mc);
Console.WriteLine(writer.ToString());

आउटपुट:

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MyString><![CDATA[<test>Hello World</test>]]></MyString>
</MyClass>

इससे मेरा दिन बच गया। धन्यवाद।
रॉबर्ट

4
// अगर आपको अपवाद से बचने के लिए खाली CDATA की आवश्यकता है, तो आप डिफ़ॉल्ट सेट कर सकते हैं यदि स्रोत मान शून्य है। XmlDocument().CreateCDataSection(MyString ?? String.Empty);
21

@ pr0gg3r यह भी एक ही वस्तु के लिए deserializing अनुमति देता है? मुझे इससे परेशानी हो रही है
मार्टिन

CDATA को टेक्स्ट मान के रूप में कैसे बनाएं (और तत्व के रूप में नहीं) जैसे कि <MyClass> <! [CDATA [<test> Hello World </ test>]> </ MyClass>?
MKO

1
केवल खाली / अशक्त मानों को आउटपुट करने की तुलना में सक्षम करने की आवश्यकता है <खाली क्षेत्र> <! [CDATA []]> </ blankfield>
ब्लू '

91

जॉन सॉन्डर्स द्वारा पोस्ट किए गए तरीके के अलावा, आप सीधे टाइप के रूप में एक XmlCDataSection का उपयोग कर सकते हैं , हालांकि यह लगभग एक ही चीज़ को उबालता है:

private string _message;
[XmlElement("CDataElement")]
public XmlCDataSection Message
{  
    get 
    { 
        XmlDocument doc = new XmlDocument();
        return doc.CreateCDataSection( _message);
    }
    set
    {
        _message = value.Value;
    }
}

1
@Philip, क्या यह डिसरसाइजेशन के लिए काम करता है? मैं यह कहते हुए नोट देख रहा हूं कि सेटर को XmlText वैल्यू मिलेगी।
जॉन सॉन्डर्स

1
@ जॉन सॉन्डर्स - यह वास्तव में deserialization के दौरान सेटर में एक XmlCharacterData मान प्राप्त करता है, जो कि कॉल करने के लिए है।
वाल्टर

1
@PhilipRieck अगर हमें CDataSection के आसपास कस्टम ऑब्जेक्ट को लपेटने की आवश्यकता है तो क्या होगा। CDataSection बनाएँ स्ट्रिंग को स्वीकार करता है।
ज़ेपेलिन

धन्यवाद! सबसे आसान समाधान। मेरे लिए ठीक काम करता है।
एंटोनियो रॉड्रिग्ज

43

क्रमबद्ध होने के लिए कक्षा में:

public CData Content { get; set; }

और सीडीटा वर्ग:

public class CData : IXmlSerializable
{
    private string _value;

    /// <summary>
    /// Allow direct assignment from string:
    /// CData cdata = "abc";
    /// </summary>
    /// <param name="value">The string being cast to CData.</param>
    /// <returns>A CData object</returns>
    public static implicit operator CData(string value)
    {
        return new CData(value);
    }

    /// <summary>
    /// Allow direct assignment to string:
    /// string str = cdata;
    /// </summary>
    /// <param name="cdata">The CData being cast to a string</param>
    /// <returns>A string representation of the CData object</returns>
    public static implicit operator string(CData cdata)
    {
        return cdata._value;
    }

    public CData() : this(string.Empty)
    {
    }

    public CData(string value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return _value;
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        _value = reader.ReadElementString();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteCData(_value);
    }
}

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

3
यह उत्तर अधिक मान्यता का हकदार है। हालाँकि, अनुकूलित CData प्रकार में अब वे सुविधाजनक तरीके नहीं हैं, जो System.String प्रकार का आनंद लेते हैं।
लियोनेट चेन

अच्छा तो पहला जवाब
Hsin-Yu Chen

उत्तर शानदार काम करता है। यह शर्म की बात है कि XmlElement स्ट्रिंग फ़ील्ड पर काम नहीं करता है, तो आप सिर्फ एक सीडीटा प्रकार जोड़ सकते हैं, लेकिन जो भी ...
jjxtra

उत्तम! धन्यवाद!
रॉय

5

मुझे एक समान आवश्यकता थी लेकिन एक अलग आउटपुट प्रारूप की आवश्यकता थी - मुझे नोड पर एक विशेषता चाहिए थी जिसमें सीडीएटीए शामिल है। मैंने अपने स्वयं के बनाने के लिए उपरोक्त समाधानों से कुछ प्रेरणा ली। शायद यह भविष्य में किसी की मदद करेगा ...

public class EmbedScript
{
    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlText]
    public XmlNode[] Script { get; set; }

    public EmbedScript(string type, string script)
    {
        Type = type;
        Script = new XmlNode[] { new XmlDocument().CreateCDataSection(script) };
    }

    public EmbedScript()
    {

    }
}

क्रमबद्ध होने की मूल वस्तु में, मेरे पास निम्नलिखित गुण हैं:

    [XmlArray("embedScripts")]
    [XmlArrayItem("embedScript")]
    public List<EmbedScript> EmbedScripts { get; set; }

मुझे निम्न आउटपुट मिले:

<embedScripts>
    <embedScript type="Desktop Iframe">
        <![CDATA[<div id="play_game"><iframe height="100%" src="http://www.myurl.com" width="100%"></iframe></div>]]>
    </embedScript>
    <embedScript type="JavaScript">
        <![CDATA[]]>
    </embedScript>
</embedScripts>

1
मुझे ठीक यही करने की जरूरत थी। धन्यवाद!!
लूइस थेरिन

4

मेरे मामले में मैं मिश्रित क्षेत्रों का उपयोग कर रहा हूं, कुछ सीडीएटीए कुछ नहीं, कम से कम मेरे लिए निम्न समाधान काम कर रहा है ...।

हमेशा वैल्यू फ़ील्ड को पढ़कर, मुझे सामग्री मिल रही है, भले ही सीडीएटीए या सिर्फ सादा पाठ हो।

    [XmlElement("")]
    public XmlCDataSection CDataValue {
        get {
            return new XmlDocument().CreateCDataSection(this.Value);
        }
        set {
            this.Value = value.Value;
        }
    }

    [XmlText]
    public string Value;

देर आए दुरुस्त आए।

चियर्स


शानदार - मुझे लग रहा है कि इस जवाब ने मुझे समय का एक हिस्सा बचा लिया! जानकारी के लिए मैंने मूल्य पर [XmlIgnore] विशेषता का उपयोग किया
d219

यह pr0gg3r के उत्तर से परिचालन रूप से कैसे भिन्न है ?
रफिन

2

यह कार्यान्वयन आपके द्वारा एन्कोड किए जा रहे स्ट्रिंग के भीतर नेस्टेड CDATA को संसाधित करने की क्षमता है (जॉन सॉन्डर्स मूल उत्तर पर आधारित)।

उदाहरण के लिए, मान लें कि आप निम्नलिखित शाब्दिक स्ट्रिंग को CDATA में बदलना चाहते थे:

I am purposefully putting some <![CDATA[ cdata markers right ]]> in here!!

आप परिणामी आउटपुट को कुछ इस तरह देखना चाहेंगे:

<![CDATA[I am purposefully putting some <![CDATA[ cdata markers right ]]]]><![CDATA[> in here!!]]>

स्ट्रिंग पर निम्नलिखित कार्यान्वयन इच्छा पाश, के उदाहरण को विभाजित ...]]>...में ...]]और >...और प्रत्येक के लिए अलग CDATA भाग पैदा करते हैं।

[XmlRoot("root")]
public class Sample1Xml
{
    internal Sample1Xml()
    {
    }

    [XmlElement("node")]
    public NodeType Node { get; set; }

    #region Nested type: NodeType

    public class NodeType
    {
        [XmlAttribute("attr1")]
        public string Attr1 { get; set; }

        [XmlAttribute("attr2")]
        public string Attr2 { get; set; }

        [XmlIgnore]
        public string Content { get; set; }

        [XmlText]
        public XmlNode[] CDataContent
        {
            get
            {
                XmlDocument dummy = new XmlDocument();
                List<XmlNode> xmlNodes = new List<XmlNode>();
                int tokenCount = 0;
                int prevSplit = 0;
                for (int i = 0; i < Content.Length; i++)
                {
                    char c = Content[i];
                    //If the current character is > and it was preceded by ]] (i.e. the last 3 characters were ]]>)
                    if (c == '>' && tokenCount >= 2)
                    {
                        //Put everything up to this point in a new CData Section
                        string thisSection = Content.Substring(prevSplit, i - prevSplit);
                        xmlNodes.Add(dummy.CreateCDataSection(thisSection));
                        prevSplit = i;
                    }
                    if (c == ']')
                    {
                        tokenCount++;
                    }
                    else
                    {
                        tokenCount = 0;
                    }
                }
                //Put the final part of the string into a CData section
                string finalSection = Content.Substring(prevSplit, Content.Length - prevSplit);
                xmlNodes.Add(dummy.CreateCDataSection(finalSection));

                return xmlNodes.ToArray();
            }
            set
            {
                if (value == null)
                {
                    Content = null;
                    return;
                }

                if (value.Length != 1)
                {
                    throw new InvalidOperationException(
                        String.Format(
                            "Invalid array length {0}", value.Length));
                }

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