如何使用XmlSerializer将字符串序列化为CDATA?

jam*_*vey 84 .net c# xml-serialization

是否可以通过某种属性将字符串序列化为使用.Net XmlSerializer的CDATA?

pr0*_*g3r 94

[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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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());
Run Code Online (Sandbox Code Playgroud)

输出:

<?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>
Run Code Online (Sandbox Code Playgroud)

  • //如果您需要空CDATA,您可以设置默认值,如果源值为null以避免异常.`XmlDocument().CreateCDataSection(MyString ?? String.Empty);` (4认同)

Phi*_*eck 89

除了John Saunders发布的方式之外,您可以直接使用XmlCDataSection作为类型,尽管它可以归结为几乎相同的东西:

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


Joh*_*ers 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
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这似乎不是最优雅的解决方案.这是唯一可行的方法吗? (8认同)
  • 菲利普的解决方案稍微偏离页面是一件更整洁的事情. (2认同)

sag*_*gis 35

在要序列化的类中:

public CData Content { get; set; }
Run Code Online (Sandbox Code Playgroud)

和CData类:

public class CData : IXmlSerializable
{
    private string _value;

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

    /// <summary>
    /// Allow direct assigment to string
    /// string str = cdata;
    /// </summary>
    /// <param name="cdata"></param>
    /// <returns></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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案值得更多的认可.虽然,定制的CData类型不再具有System.String类型所享有的那些方便的内置方法. (2认同)

Ada*_*Hey 6

我有类似的需求,但需要不同的输出格式 - 我想要包含 CDATA 的节点上的属性。我从上述解决方案中汲取了一些灵感来创建自己的解决方案。也许它会在未来帮助某人......

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()
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

在要序列化的父对象中,我具有以下属性:

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

我得到以下输出:

<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>
Run Code Online (Sandbox Code Playgroud)