C# XML序列化-XMLCDATA节作为Serialization.XmlText

C# XML序列化-XMLCDATA节作为Serialization.XmlText,c#,xml,xml-serialization,cdata,C#,Xml,Xml Serialization,Cdata,我在使用c序列化cdata节时遇到问题# 我需要将XmlCDataSection对象属性序列化为元素的innertext 我想要的结果是: <Test value2="Another Test"> <![CDATA[<p>hello world</p>]]> </Test> 在value属性上使用xmltext注释时,会引发以下错误 System.InvalidOperationException: 反映属性时出错 “值”。-->

我在使用c序列化cdata节时遇到问题#

我需要将XmlCDataSection对象属性序列化为元素的innertext

我想要的结果是:

<Test value2="Another Test">
  <![CDATA[<p>hello world</p>]]>
</Test>
在value属性上使用xmltext注释时,会引发以下错误

System.InvalidOperationException: 反映属性时出错 “值”。--> System.InvalidOperationException: 无法序列化的成员“值” 键入System.Xml.xmlcatasection。 XmlAttribute/XmlText不能用于 编码复杂类型

如果我注释掉注释,序列化将起作用,但cdata部分被放入一个value元素中,这对我尝试执行的操作没有好处:

<Test value2="Another Test">
  <value><![CDATA[<p>hello world</p>]]></value>
</Test>

你好,世界

]>
有谁能给我指点正确的方向,让这项工作顺利进行吗


谢谢,Adam

按照
Test
的定义,您的数据是一个CData对象。因此,序列化系统试图保留CData对象

但您希望将一些文本数据序列化为CData节

因此,首先,
Test.value
的类型应该是String

然后,您需要控制该字段的序列化方式,但似乎没有任何内置方法或属性来控制字符串的序列化方式(作为字符串,可能带有保留字符的实体,或作为CDATA)。(因为从XML信息集的角度来看,所有这些都是相同的,所以这并不奇怪。)


当然,您可以实现IXmlSerializable,只需自己编写
测试的序列化代码,就可以完全控制。

谢谢Richard,现在才有机会回到这一点。我想我利用你的建议解决了这个问题。我使用以下方法创建了CDATA字段对象:

public class CDataField : IXmlSerializable
    {
        private string elementName;
        private string elementValue;

        public CDataField(string elementName, string elementValue)
        {
            this.elementName = elementName;
            this.elementValue = elementValue;
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void WriteXml(XmlWriter w)
        {
            w.WriteStartElement(this.elementName);
            w.WriteCData(this.elementValue);
            w.WriteEndElement();
        }

        public void ReadXml(XmlReader r)
        {                      
            throw new NotImplementedException("This method has not been implemented");
        }
    }

我和亚当有同样的问题。然而,这个答案并没有100%的帮助我:)但给了我一个线索。所以我创建了如下代码。它生成的XML如下所示:

<Actions>
    <Action Type="reset">
      <![CDATA[
      <dbname>longcall</dbname>
      <ontimeout>
       <url>http://[IPPS_ADDRESS]/</url>
       <timeout>10</timeout>
      </ontimeout>
      ]]>
    </Action>
    <Action Type="load">
      <![CDATA[
      <dbname>longcall</dbname>
      ]]>
    </Action>
</Actions>

长途电话
http://[IPPS_地址]/
10
]]>
长途电话
]]>
代码:

公共类ActionsCDataField:IXmlSerializable
{
公共列表操作{get;set;}
公共操作数据字段()
{
Actions=新列表();
}
公共XmlSchema GetSchema()
{
返回null;
}
公共void WriteXml(XmlWriter w)
{
foreach(行动中的var项目)
{
w、 书面启动(“行动”);
w、 WriteAttributeString(“类型”,item.Type);
w、 WriteCData(item.InnerText);
w、 写删除();
w、 写入字符串(“\r\n”);
}
}
公共void ReadXml(XmlReader r)
{
XmlDocument xDoc=新的XmlDocument();
xDoc.荷载(r);
XmlNodeList节点=xDoc.GetElementsByTagName(“操作”);
if(nodes!=null&&nodes.Count>0)
{
foreach(节点中的XmlElement节点)
{
动作a=新动作();
a、 Type=node.GetAttribute(“Type”);
a、 InnerText=node.InnerXml;
if(a.InnerText!=null&&a.InnerText.StartsWith(“”)
a、 InnerText=a.InnerText.Substring(“.Length”);
行动.添加(a);
}
}
}
}
公共集体诉讼
{
公共字符串类型{get;set;}
公共字符串InnerText{get;set;}
}

刚刚从以下位置找到了替代方案:


Jack answer的这个基本上较短的版本具有更好的错误消息:

[XmlIgnore]
公共字符串内容{get;set;}
[XmlText]
公共XmlNode[]ContentAsCData
{
get=>new[]{new XmlDocument().CreateCataSection(内容)};
set=>Content=value?.Cast()?.Single()?.Data;
}

如果删除
[XmlText]
会发生什么?它抛出
A.cdata字段无法序列化,因为它没有无参数构造函数
错误
<Actions>
    <Action Type="reset">
      <![CDATA[
      <dbname>longcall</dbname>
      <ontimeout>
       <url>http://[IPPS_ADDRESS]/</url>
       <timeout>10</timeout>
      </ontimeout>
      ]]>
    </Action>
    <Action Type="load">
      <![CDATA[
      <dbname>longcall</dbname>
      ]]>
    </Action>
</Actions>
public class ActionsCDataField : IXmlSerializable
{
    public List<Action> Actions { get; set; }

    public ActionsCDataField()
    {
        Actions = new List<Action>();
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void WriteXml(XmlWriter w)
    {
        foreach (var item in Actions)
        {
            w.WriteStartElement("Action");
            w.WriteAttributeString("Type", item.Type);
            w.WriteCData(item.InnerText);                
            w.WriteEndElement();
            w.WriteString("\r\n");
        }
    }

    public void ReadXml(XmlReader r)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(r);

        XmlNodeList nodes = xDoc.GetElementsByTagName("Action");
        if (nodes != null && nodes.Count > 0)
        {
            foreach (XmlElement node in nodes)
            {
                Action a = new Action();
                a.Type = node.GetAttribute("Type");
                a.InnerText = node.InnerXml;
                if (a.InnerText != null && a.InnerText.StartsWith("<![CDATA[") && a.InnerText.EndsWith("]]>"))
                    a.InnerText = a.InnerText.Substring("<![CDATA[".Length, a.InnerText.Length - "<![CDATA[]]>".Length);

                Actions.Add(a);
            }
        }
    }
}

public class Action
{
    public String Type { get; set; }
    public String InnerText { 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));
                    }

                    var node0 = value[0];
                    var cdata = node0 as XmlCDataSection;
                    if (cdata == null)
                    {
                        throw new InvalidOperationException(
                            String.Format(
                                "Invalid node type {0}", node0.NodeType));
                    }

                    Content = cdata.Data;
                }
            }
        }