8

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

我需要将 XmlCDataSection 对象属性序列化为元素的内部文本。

我正在寻找的结果是这样的:

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

为了产生这个,我正在使用这个对象:

public class Test
{
    [System.Xml.Serialization.XmlText()]
    public XmlCDataSection value { get; set; }

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string value2 { get; set; }
}

在 value 属性上使用 xmltext 注释时,会引发以下错误。

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

如果我注释掉注释,序列化将起作用,但 cdata 部分被放置到一个值元素中,这对我想要做的事情没有好处:

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

任何人都可以指出我正确的方向来让它发挥作用。

谢谢,亚当

4

5 回答 5

5

谢谢理查德,现在才有机会回到这个话题。我想我已经通过使用你的建议解决了这个问题。我使用以下内容创建了一个 CDataField 对象:

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");
        }
    }
于 2009-10-22T13:27:06.937 回答
2

方式Test已定义,您的数据是一个 CData 对象。所以序列化系统试图保留 CData 对象。

但是您想将一些文本数据序列化为 CData 部分。

所以首先,类型Test.value应该是String。

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

您当然可以实现 IXmlSerializable 并Test自己编写类型的序列化代码,从而完全控制。

于 2009-09-09T11:43:22.647 回答
1

刚刚找到了一个替代方案here

     [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;
                }
            }
        }
于 2015-08-05T02:23:29.073 回答
1

这个基本上较短版本的 Jack 回答了更好的错误消息:

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

[XmlText]
public XmlNode[] ContentAsCData
{
    get => new[] { new XmlDocument().CreateCDataSection(Content) };
    set => Content = value?.Cast<XmlCDataSection>()?.Single()?.Data;
}
于 2019-08-15T17:50:03.283 回答
0

我和亚当有同样的问题。然而,这个答案并没有 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>

代码:

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; }
}
于 2014-01-27T09:42:10.510 回答