Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用XmlSerializer将字符串序列化为CDATA?_C#_.net_Xml Serialization - Fatal编程技术网

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

C# 如何使用XmlSerializer将字符串序列化为CDATA?,c#,.net,xml-serialization,C#,.net,Xml Serialization,是否可以通过某种类型的属性使用.Net XmlSerializer将字符串序列化为CDATA?除了John Saunders发布的方法外,您还可以直接使用a作为类型,尽管它可以归结为几乎相同的东西: [XmlRoot("root")] public class Sample1Xml { internal Sample1Xml() { } [XmlElement("node")] public NodeType Node { get; set; }

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

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

[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
}
private string _message;
[XmlElement("CDataElement")]
public XmlCDataSection Message
{  
    get 
    { 
        XmlDocument doc = new XmlDocument();
        return doc.CreateCDataSection( _message);
    }
    set
    {
        _message = 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());
MyClass mc=newmyclass();
mc.MyString=“你好,世界”;
XmlSerializer serializer=新的XmlSerializer(typeof(MyClass));
StringWriter编写器=新的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>

你好,世界]]>

在要序列化的类中:

public CData Content { get; set; }
和CData类:

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);
    }
}
公共类CData:IXmlSerializable
{
私有字符串_值;
/// 
///允许从字符串直接赋值:
///CData=“abc”;
/// 
///正在转换为CData的字符串。
///CData对象
公共静态隐式运算符CData(字符串值)
{
返回新的CData(值);
}
/// 
///允许直接分配到字符串:
///字符串str=cdata;
/// 
///正在转换为字符串的CData
///CData对象的字符串表示形式
公共静态隐式运算符字符串(CData)
{
返回cdata.\u值;
}
公共CData():此(string.Empty)
{
}
公共CData(字符串值)
{
_价值=价值;
}
公共重写字符串ToString()
{
返回_值;
}
public System.Xml.Schema.XmlSchema GetSchema()
{
返回null;
}
public void ReadXml(System.Xml.XmlReader)
{
_value=reader.ReadElementString();
}
public void WriteXml(System.Xml.XmlWriter)
{
writer.WriteCData(_值);
}
}

此实现能够处理编码字符串中的嵌套CDATA(基于John Saunders的原始答案)

例如,假设您希望将以下文字字符串编码为CDATA:

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

在我的例子中,我使用的是混合字段,有些是CDATA,有些不是, 至少对我来说,以下解决方案是有效的

通过始终读取值字段,我得到了内容,无论是CDATA还是纯文本

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

    [XmlText]
    public string Value;
迟做总比不做好


Cheers

我也有类似的需求,但需要不同的输出格式-我希望在包含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()
    {

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

    [XmlArray("embedScripts")]
    [XmlArrayItem("embedScript")]
    public List<EmbedScript> EmbedScripts { get; set; }
[XmlArray(“嵌入脚本”)]
[XmlArrayItem(“嵌入脚本”)]
公共列表{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>

]]>
这很有效

using System.Collections.ObjectModel;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;

public class CDataContent
{
    public CDataContent()
    {
    }

    public CDataContent(string content)
    {
        this.Content = content;
    }

    [XmlIgnore]
    public string Content
    {
        get => this.CData.FirstOrDefault()?.Value;
        set
        {
            this.CData.Clear();
            this.CData.Add(new XmlDocument().CreateCDataSection(value));
        }
    }

    [XmlText]
    public Collection<XmlNode> CData { get; } = new();

    public static implicit operator CDataContent(string value) => new(value);

    public static implicit operator string(CDataContent value) => value.Content;
}
使用System.Collections.ObjectModel;
使用System.Linq;
使用System.Xml;
使用System.Xml.Serialization;
公共类CDATA内容
{
公共内容()
{
}
公共CDATA内容(字符串内容)
{
这个。内容=内容;
}
[XmlIgnore]
公共字符串内容
{
get=>this.CData.FirstOrDefault()?.Value;
设置
{
this.CData.Clear();
this.CData.Add(新的XmlDocument().createCDATA节(值));
}
}
[XmlText]
公共集合CData{get;}=new();
公共静态隐式运算符CDATA内容(字符串值)=>new(值);
公共静态隐式运算符字符串(CDATA内容值)=>value.Content;
}


对我来说,这似乎不是最优雅的解决方案。这是唯一可行的方法吗?我认为这是实现这一目标的唯一方法,我在其他地方看到过这个话题,答案总是一样的。Philip的例子有点简洁,但概念相同。我所知道的唯一的另一种方法是在表示CDATA内容的类上实现您自己的>。我想做同样的事情,因为似乎将字符串存储为CDATA意味着更少的处理时间,因为我们“只能按原样”读/写字符串。涉及XmlDocument/xmlcatasection实例的代价有多高?整个属性都在那里,因此我们能够保持域模型类不受序列化逻辑细节的影响。如果肮脏的方式是唯一的方式,那就太可悲了。Philip的解决方案在页面后面稍微靠远一点是一件更整洁的事情。@Philip,这对反序列化有用吗?我看到一些注释说setter将接收一个XmlText值。@John Saunders-在反序列化过程中,它实际上在setter中接收一个XmlCharacterData值,这就是对.value的调用在setter中的作用(我最初将其作为内存中的ToString(),但这是不正确的)@PhilipRieck如果我们需要在CDATA节周围包装一个自定义对象,该怎么办。创建CDATA节接受字符串。谢谢!最简单的解决方案。这两个答案中值得注意的一点是,如果您只阅读XML,则不需要
CDATA内容
XmlSerializer.Deserialize
将自动为您将其转换为文本。这刚刚节省了我的时间。谢谢//如果您需要空的CDATA,您可以在源值为空时设置默认值以避免异常<代码>XmlDocument().CreateCataSection(MyString??String.Empty)@pr0gg3r这是否也允许反序列化到同一对象?我遇到了这样的问题:如何将CDATA创建为文本值(而不是元素),例如Hello World]]]>?只需要能够处理空/空值,而不是像符咒一样输出。谢谢。这个答案值得更多的认可。尽管如此,定制的CData类型不再具有System.String类型喜欢的那些方便的内置方法。遗憾的是XmlElement不能处理字符串字段,然后您可以添加一个cdata类型,但不管怎样……太完美了!谢谢我需要做exac
    [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>
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;

public class CDataContent
{
    public CDataContent()
    {
    }

    public CDataContent(string content)
    {
        this.Content = content;
    }

    [XmlIgnore]
    public string Content
    {
        get => this.CData.FirstOrDefault()?.Value;
        set
        {
            this.CData.Clear();
            this.CData.Add(new XmlDocument().CreateCDataSection(value));
        }
    }

    [XmlText]
    public Collection<XmlNode> CData { get; } = new();

    public static implicit operator CDataContent(string value) => new(value);

    public static implicit operator string(CDataContent value) => value.Content;
}