C# 如何防止XmlSerializer转义;嵌套XML;?

C# 如何防止XmlSerializer转义;嵌套XML;?,c#,xml,escaping,xml-serialization,xmlserializer,C#,Xml,Escaping,Xml Serialization,Xmlserializer,我正在使用XmlSerializer对复杂对象进行序列化/反序列化。一个属性包含一个XML字符串,该字符串应在不进行反序列化的情况下写入字符串属性 示例(在LinqPad中可执行): [XmlRoot("RootObject")] [Serializable] public class RootClass { [XmlArray("SubObjects")] [XmlArrayItem("SubObject")] public SubClass[] SubObjecs {

我正在使用XmlSerializer对复杂对象进行序列化/反序列化。一个属性包含一个XML字符串,该字符串应在不进行反序列化的情况下写入字符串属性

示例(在LinqPad中可执行):

[XmlRoot("RootObject")]
[Serializable]
public class RootClass
{
    [XmlArray("SubObjects")]
    [XmlArrayItem("SubObject")]
    public SubClass[] SubObjecs { get; set;} 
}

[Serializable]
public class SubClass
{
    [XmlElement("XmlConfiguration")]
    public string XmlConfiguration { get; set;}
}

void Main()
{
    var obj = new RootClass()
    {
        SubObjecs = new[]
        {
            new SubClass { XmlConfiguration = "<ConfigurationX>SomeConfiguration1</ConfigurationX>" },
            new SubClass { XmlConfiguration = "<ConfigurationY>SomeConfiguration2</ConfigurationY>" }
        }
    };

    var serializer = new XmlSerializer(typeof(RootClass));
    using (var stream = new MemoryStream())
    {
        serializer.Serialize(stream, obj);
        stream.Position = 0;
        Console.WriteLine(Encoding.UTF8.GetString(stream.GetBuffer()));
    }
}
[XmlRoot(“RootObject”)]
[可序列化]
公共类根类
{
[XmlArray(“子对象”)]
[XmlArrayItem(“子对象”)]
公共子类[]子对象{get;set;}
}
[可序列化]
公共类子类
{
[XmlElement(“XmlConfiguration”)]
公共字符串XmlConfiguration{get;set;}
}
void Main()
{
var obj=新根类()
{
SubObjecs=new[]
{
新的子类{XmlConfiguration=“SomeConfiguration1”},
新的子类{XmlConfiguration=“SomeConfiguration2”}
}
};
var serializer=newxmlserializer(typeof(RootClass));
使用(var stream=new MemoryStream())
{
serializer.Serialize(流,obj);
流位置=0;
Console.WriteLine(Encoding.UTF8.GetString(stream.GetBuffer());
}
}
示例的输出为:

<?xml version="1.0"?>
<RootObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SubObjects>
        <SubObject>
            <XmlConfiguration>&lt;ConfigurationX&gt;SomeConfiguration1&lt;/ConfigurationX&gt;</XmlConfiguration>
        </SubObject>
        <SubObject>
            <XmlConfiguration>&lt;ConfigurationY&gt;SomeConfiguration2&lt;/ConfigurationY&gt;</XmlConfiguration>
        </SubObject>
    </SubObjects>
</RootObject>

配置XSomeConfiguration1/ConfigurationX
配置SomeConfiguration2/ConfigurationY
XML是一个配置文件,有时以编程方式编写,但主要由人编写/修改。因此
XmlConfiguration
中的XML不应包含转义字符

问题: 是否可以防止XmlSerializer转义“”字符?如果没有,是否可以使用其他序列化程序

一个可行的选择是。然而,如果可能的话,我会避免这种不可靠、不易维护的解决方案



我在这里发现了一个类似的问题:。但这个问题是与我们有关的!CDATA[[Content]]没有回答我的问题。

正如dbc在评论中提到的,有一个解决方案使用了
xmlanyement
属性,如下所述:


我找到了一个混合了
XmlSerializer
XmlWriter.WriteRaw
的解决方案。在实现
IXmlSerializable
时,可以控制
XmlSerializer
的序列化过程。因此,必须仅为需要特殊处理的类实现IXmlSerializable(这对我来说没问题):


如果您需要CDATA封装,可以使用它。您可以将以下类作为xml元素的类型。您可以根据需要为每种不同类型的元素更改名称或属性

public class XmlConfiguration //Or any other class name.
    {
        [XmlAttribute("attr1")]
        public string Attr1 { get; set; } //You don't need this but use if you need attribute.

        [XmlAttribute("attr2")]
        public string Attr2 { get; set; } //Or second one.

        [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;
            }
        }
    }

我找到了这个答案。查看完整讨论的链接。

您可以在嵌套的
XmlConfiguration
类上使用
[xmlanyement]
[XmlAnyAttribute]
。请参阅。顺便说一句,如果您更喜欢LINQ而不是XML,而不是旧的
XmlDocument
,那么
List
将与
xmlanyement
一起使用(尽管
List
无法与
[XmlAnyAttribute]
一起使用,这很奇怪。)请参见示例。@dbc:很好,谢谢!还可以将
[xmlanyement]
XElement
结合使用(无列表)。你想写下你的评论作为答案吗?
public class XmlConfiguration //Or any other class name.
    {
        [XmlAttribute("attr1")]
        public string Attr1 { get; set; } //You don't need this but use if you need attribute.

        [XmlAttribute("attr2")]
        public string Attr2 { get; set; } //Or second one.

        [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;
            }
        }
    }