【问题标题】:XML serialization force full closing tag on null or empty valueXML 序列化在 null 或空值上强制使用完整的结束标记
【发布时间】:2016-11-04 12:34:44
【问题描述】:

我有课

public class Testowa
{
    public string test { get; set; }
}

当我将它序列化而没有测试价值时,我得到

<test/>

但我想得到

<test></test>

我该怎么做?

【问题讨论】:

  • 它们的意思是一样的。为什么重要?
  • &lt;test/&gt;&lt;test&gt;&lt;/test&gt; 在 XML 中是等价的。为什么差异对您来说很重要?
  • 我必须适应clinet规范。我不知道他为什么要这样。
  • 除此之外,您还没有告诉我们您尝试了什么,甚至没有告诉我们您将如何序列化课程。这里没有足够的信息。
  • 当一个人问“如何?”时,不要用“为什么?”来使其无效。这是我在请求完整结束标签时遇到的一个案例:一个遗留应用程序正在被改造。它必须逐步改进,目前关注的领域是对象的序列化。正在定义新的公共属性,开发人员希望能够将 XML 作为一种可以重新加载的模板进行手动编辑。当您需要几十个节点时,使用完整的结束标记可以减少文本元素的输入玩弄。

标签: c# xml serialization


【解决方案1】:

扩展 XmlWriter

来自there

如果您使用类似于以下的代码进行序列化:

XmlSerializer s = new XmlSerializer(typeof(Testowa));
using (FileStream fs = new FileStream(File, FileMode.CreateNew))
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Encoding = Encoding.GetEncoding("ISO-8859-1");
    settings.NewLineChars = Environment.NewLine;
    settings.ConformanceLevel = ConformanceLevel.Document;
    settings.Indent = true;
    using (XmlWriter writer = XmlWriter.Create(fs, settings))
    {
        s.Serialize(writer, this);
    }
}

用派生版本的XmlWriter 替换最后一行,这将强制序列化完整的结束标签:

s.Serialize(new XmlWriterEE(writer), this);

完整的 XmlWriter 派生类:

public class XmlWriterEE :  XmlWriter
{
    private XmlWriter baseWriter;

    public XmlWriterEE(XmlWriter w)
    {
        baseWriter = w;
    }

    //Force WriteEndElement to use WriteFullEndElement
    public override void WriteEndElement() {baseWriter.WriteFullEndElement(); }

    public override void WriteFullEndElement()
    {
        baseWriter.WriteFullEndElement();
    }

    public override void Close()
    {
        baseWriter.Close();
    }

    public override void Flush()
    {
        baseWriter.Flush();
    }

    public override string LookupPrefix(string ns)
    {
        return (baseWriter.LookupPrefix(ns));
    }

    public override void WriteBase64(byte[] buffer, int index, int count)
    {
        baseWriter.WriteBase64(buffer, index, count);
    }

    public override void WriteCData(string text)
    {
        baseWriter.WriteCData(text);
    }

    public override void WriteCharEntity(char ch)
    {
        baseWriter.WriteCharEntity(ch);
    }

    public override void WriteChars(char[] buffer, int index, int count)
    {
        baseWriter.WriteChars(buffer, index, count);
    }

    public override void WriteComment(string text)
    {
        baseWriter.WriteComment(text);
    }

    public override void WriteDocType(string name, string pubid, string sysid, string subset)
    {
        baseWriter.WriteDocType(name, pubid, sysid, subset);
    }

    public override void WriteEndAttribute()
    {
        baseWriter.WriteEndAttribute();
    }

    public override void WriteEndDocument()
    {
        baseWriter.WriteEndDocument();
    }

    public override void WriteEntityRef(string name)
    {
        baseWriter.WriteEntityRef(name);
    }

    public override void WriteProcessingInstruction(string name, string text)
    {
        baseWriter.WriteProcessingInstruction(name, text);
    }

    public override void WriteRaw(string data)
    {
        baseWriter.WriteRaw(data);
    }

    public override void WriteRaw(char[] buffer, int index, int count)
    {
        baseWriter.WriteRaw(buffer, index, count);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        baseWriter.WriteStartAttribute(prefix, localName, ns);
    }

    public override void WriteStartDocument(bool standalone)
    {
        baseWriter.WriteStartDocument(standalone);
    }

    public override void WriteStartDocument()
    {
        baseWriter.WriteStartDocument();
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        baseWriter.WriteStartElement(prefix, localName, ns);
    }

    public override WriteState WriteState
    {
        get { return baseWriter.WriteState; }
    }

    public override void WriteString(string text)
    {
        baseWriter.WriteString(text);
    }

    public override void WriteSurrogateCharEntity(char lowChar, char highChar)
    {
        baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
    }

    public override void WriteWhitespace(string ws)
    {
        baseWriter.WriteWhitespace(ws);
    }
}

【讨论】:

  • 试过这个,没用,拔掉我的头发,花了好几个小时试图弄清楚为什么它不起作用或我应该做什么以及为什么没有人有当前的解决方案.. . 然后我意识到我是在 Windows 默认的 XML 应用程序 - Internet Explorer 中打开生成的 XML 文件。 IE 正在加载 XML 文件并以“现代”XML 标准重新显示它。当我在 Notepad++ 中打开实际文件时,我看到打开和关闭标签实际上就在文件中。我假设 IE 加载了文档并使用他们自己的 XML 查看器显示它,该查看器将 &lt;tag&gt;&lt;/tag&gt; 转换为 &lt;tag/&gt;
【解决方案2】:

如果你不使用 FileStream,你可以使用 StringBuilder。来自Fab 帖子的 XmlWriterEE 类。

    public static string SerializeObject(this object obj)
    {
        var settings = new XmlWriterSettings
        {
            Encoding = Encoding.GetEncoding("ISO-8859-1"),
            NewLineChars = Environment.NewLine,
            ConformanceLevel = ConformanceLevel.Auto,
            OmitXmlDeclaration = true,
            WriteEndDocumentOnClose = true,
            Indent = true
        };           

        var stream = new StringBuilder();

        using (var writer = XmlWriter.Create(stream, settings))
        {
            var xmlSerializer = new XmlSerializer(obj.GetType());
            var namespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
            xmlSerializer.Serialize(new XmlWriterEE(writer), obj, namespaces);                
        }
        return stream.ToString();
    }

【讨论】:

    猜你喜欢
    • 2019-07-29
    • 1970-01-01
    • 2022-01-21
    • 2017-07-26
    • 1970-01-01
    • 2022-06-10
    • 2015-03-19
    • 2017-12-29
    • 2011-10-11
    相关资源
    最近更新 更多