【问题标题】:Modifying the outputted xml of a DataContractSerializer修改 DataContractSerializer 的输出 xml
【发布时间】:2011-07-27 14:22:53
【问题描述】:

我的 WCF 服务使用 DataContractSerializer 序列化我的对象并将它们发送到客户端。我目前在输出 xml 的格式方面遇到问题。

我需要:

  1. 获取我的 WCF 服务使用的 DataSerializer

  2. 改变它,让它像这样输出 xml:

    <node></node>
    

    而不是那个

    <node />
    

那么,我将如何访问我的序列化程序,然后我如何更改其设置以便写入完整的结束元素。

【问题讨论】:

  • 开始标签和结束标签之间有空格吗?请注意,它们不一样。 &lt;node /&gt; 表示标签内没有任何内容。 &lt;node&gt; &lt;/node&gt; 表示单个空格。 &lt;node /&gt;&lt;node&gt;&lt;/node&gt; 一样,没有空格,所以你不能解析 &lt;node /&gt; 有什么原因吗?
  • 感谢评论,没有空间了。
  • 我有一个单点触控客户端,它无法解析像 这样的空节点的字典
  • 可能已经在这里回答了:stackoverflow.com/questions/1971743/…
  • @Jean-Phillippe 坦率地说,这是读者的一个错误。作者做得很好……

标签: c# wcf serialization


【解决方案1】:

DataContractSerializer (DCS) 不知道(关心?)表示序列化图的 XML 信息集将如何输出 - 它将其委托给 XmlWriter。作者是可以(或不能)将空元素写为&lt;a/&gt;&lt;a&gt;&lt;/a&gt; 的人——因为这两者(假定)是等价的,DCS 将使用任何元素。但是如果你控制了作者,那么你就可以控制输出。这并不难做到 - 只需创建一个包装另一个写入器的写入器,并将所有覆盖委托给内部写入器除了一个到 WriteEndElement() - 在那个写入器中,调用 Write* Full*EndElement 以确保不会写入空元素。下面的代码有这样的实现,在使用新的 writer 时会写出完整的 end 元素。

public class StackOverflow_6846012
{
    class MyWriter : XmlWriter
    {
        XmlWriter inner;
        public MyWriter(XmlWriter inner)
        {
            this.inner = inner;
        }

        public override void Close()
        {
            this.inner.Close();
        }

        public override void Flush()
        {
            this.inner.Flush();
        }

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

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

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

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

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

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

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

        public override void WriteEndAttribute()
        {
            this.inner.WriteEndAttribute();
        }

        public override void WriteEndDocument()
        {
            this.inner.WriteEndDocument();
        }

        public override void WriteEndElement()
        {
            this.inner.WriteFullEndElement();
        }

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

        public override void WriteFullEndElement()
        {
            this.inner.WriteFullEndElement();
        }

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

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

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

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

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

        public override void WriteStartDocument()
        {
            this.inner.WriteStartDocument();
        }

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

        public override WriteState WriteState
        {
            get { return this.inner.WriteState; }
        }

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

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

        public override void WriteWhitespace(string ws)
        {
            this.inner.WriteWhitespace(ws);
        }
    }
    public static void Test()
    {
        DataContractSerializer dcs = new DataContractSerializer(typeof(List<string>));
        MemoryStream ms = new MemoryStream();
        List<string> list = new List<string> { "Hello", "", "world" };
        dcs.WriteObject(ms, list);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        Console.WriteLine();

        ms.SetLength(0);
        XmlWriter myWriter = new MyWriter(XmlDictionaryWriter.CreateTextWriter(ms));
        dcs.WriteObject(myWriter, list);
        myWriter.Flush();
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}

现在,您在 WCF 中连接此编写器的地方将是自定义消息编码器。 http://msdn.microsoft.com/en-us/library/ms751486.aspx 的示例正是这样做的——它将 WCF 使用的默认编写器替换为 System.Xml.dll 程序集中的编写器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多