【问题标题】:Creating and using custom XML special characters with XmlSerializer使用 XmlSerializer 创建和使用自定义 XML 特殊字符
【发布时间】:2016-10-30 06:24:37
【问题描述】:

我有一个ColorFormat 类,用于存储有关颜色格式的基本信息。目的是能够对 XML 进行序列化和反序列化。为了表示红色、绿色和蓝色,我使用了特殊的颜色字符串标识符:

public const string RedColorIdentifier = "&red;";
public const string GreenColorIdentifier = "&green;";
public const string BlueColorIdentifier = "&blue;";

对于像“#RGB”这样的格式,类格式字符串是这样的:

colorFormat.Format = "#" + ColorFormat.RedColorIdentifier +
                           ColorFormat.GreenColorIdentifier +
                           ColorFormat.BlueColorIdentifier;

理想情况下,序列化的 XML 应该是:

<ColorFormat Name="HexFmt" ColorBase="Hex">#&red;&green;&blue;</ColorFormat>

实际的序列化是:

<ColorFormat Name="HexFmt" ColorBase="Hex">#&amp;red;&amp;green;&amp;blue;</ColorFormat>

我想知道是否有一种方法可以“序列化和反序列化”您自己的自定义特殊 XML 字符

【问题讨论】:

  • 你可以使用CDATACDATA Sections
  • XML &lt;ColorFormat Name="HexFmt" ColorBase="Hex"&gt;#&amp;red;&amp;green;&amp;blue;&lt;/ColorFormat&gt; 无效。例如。上传到xmlvalidation.com,你会得到一个错误Errors in the XML document: 1:50 The entity "red" was referenced, but not declared.
  • &amp;text; - 是 xml entity。不要使用这样的实体。使用任何其他符号代替&amp;

标签: c# xml serialization deserialization


【解决方案1】:

您可以使用CData 包装特殊字符。
来自 MSDN CDATA Section

例如下面的类将被序列化 witt 颜色值用 CData 包装

[XmlType("ColorFormat")]
public class ColorFormat
{
    [XmlAttribute]
    public string Name { get; set; }

    [XmlAttribute]
    public string ColorBase { get; set; }

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

    [XmlText]
    public XmlNode[] SerializableFormat
    {
        get
        {
            var doc = new XmlDocument();
            return new XmlNode[] { doc.CreateCDataSection(this.Format) };
        }
        set
        {
            this.Format = value[0].Value;
        }
    }
}

ColorFormat 类的使用

const string FORMAT = "&red;&green;&blue;";

var format = new ColorFormat
{
    Name = "HexFormat",
    ColorBase = "Hex",
    Format = FORMAT
};

var serializer = new XmlSerializer(typeof(ColorFormat));
using (var writer = new StringWriter())
{
    serializer.Serialize(writer, format);
    Console.WriteLine(writer.ToString());
}

【讨论】:

  • @HishamMaudarbocus,我已将SerializableFormat 更改为XmlNode[] 类型并将XmlAnyElement 属性更改为XmlText
  • 是的,就像魔术一样工作。但是,尽管这是一个很好的答案,但我对此并不太满意。 CDATA 给文件增加了太多的复杂性,因为它将由普通 PC 用户手动编辑。我在 XML 中看到了自定义实体的线索,需要进一步探索
【解决方案2】:

终于找到了,要这样实现IXmlSerializable:

public class ColorFormat : IXmlSerializable
{
    ...

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        Name = reader.GetAttribute(nameof(Name));
        ColorBase = CommonUtil.ParseStringToEnum<NumberBase>(reader.GetAttribute(nameof(ColorBase)));
        Format = reader.ReadInnerXml();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString(nameof(Name), Name);
        writer.WriteAttributeString(nameof(ColorBase), ColorBase.ToString());
        writer.WriteRaw(Format);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多