【问题标题】:Why does DataContractSerializer ignore XmlWriterSettings settings?为什么 DataContractSerializer 会忽略 XmlWriterSettings 设置?
【发布时间】:2014-04-02 06:56:01
【问题描述】:

我的数据实体包含一个字典,但 XmlSerializer 不支持开箱即用。所以我决定使用 DataContractSerializer。问题是我无法让它按照我的需要运行。

我从以下代码开始:

public static string SerializeObject<T>(T serialisable)
{
    var serializer = new DataContractSerializer(serialisable.GetType());
    using (var writer = new StringWriter())
    using (var stm = new XmlTextWriter(writer))
    {
        serializer.WriteObject(stm, serialisable);
        return writer.ToString();
    }
}

它似乎工作正常,直到我注意到如果我将“\r\n”放在一个字符串中,它不会被序列化为 XML 实体。根据我使用 XmlSerializer 的经验,我知道我可以使用 NewLineHandling = NewLineHandling.Entitize 设置 XmlWriterSettings。所以我将我的代码转换为以下内容:

public static string SerializeObject<T>(T serialisable)
{
    var serializer = new DataContractSerializer(serialisable.GetType());
    using (var writer = new StringWriter())
    {
        using (var stm = XmlWriter.Create(writer,
            new XmlWriterSettings()
            {
                NewLineHandling = NewLineHandling.Entitize
            }))
        {
            serializer.WriteObject(stm, serialisable);
            return writer.ToString();
        }
    }
}

现在的问题是我得到一个空字符串。没有例外,没有 - 只是一个空字符串。 stm 变量保存 XmlWellFormedWriter。可能 DataContractSerializer 不支持?

然后我尝试按如下方式强制执行 XmlTextWriter:

public static string SerializeObject<T>(T serialisable)
{
    var serializer = new DataContractSerializer(serialisable.GetType());
    using (var writer = new StringWriter())
    using (var stm = XmlWriter.Create(new XmlTextWriter(writer),
        new XmlWriterSettings()
        {
            NewLineHandling = NewLineHandling.Entitize
        }))
    {
        serializer.WriteObject(stm, serialisable);
        return writer.ToString();
    }
}

这让我回到了我开始的地方——我得到了 XML 字符串,但“\r\n”字符串又没有被转换为实体。

如何使 DataContractSerializer 实体化换行符并将 XML 作为字符串返回?

【问题讨论】:

    标签: .net newline encode datacontractserializer


    【解决方案1】:

    我知道这是一个相当古老的线程,但我偶然发现它正在寻找答案,并认为我会回答我发现的问题。

    \n 未被实体化的原因是因为它们位于文本节点值中。如果 \n 字符在属性中,序列化程序只会实体化它们。

    这是我发现的每个 NewLineHandling 值都会发生的情况

    文本节点

    NewLineHandling.Replace (Default) 
    \r \n \r\n all go to \r\n
    \t remains as \t
    
    NewLineHandling.Entitize
    \r\n goes to &#D;
    \n remains as \n
    \r goes to &#D;
    \t remains as \t
    
    NewLineHandling.None
    \r remains \r
    \r\n remains \n
    \r\n remains \r\n
    \t remains as \t
    

    属性

    NewLineHandling.Replace (Default) 
    \r\n goes to &#D;&#A;
    \n goes to &#A;
    \r goes to &#D;
    \t remains &#9;
    
    NewLineHandling.Entitize
    \r\n goes to &#D;&#A;
    \n goes to &#A;
    \r goes to &#D;
    \t remains &#9;
    
    NewLineHandling.None
    \r remains \r
    \r\n remains as \n
    \r\n remains as \r\n
    \t remains as \t
    

    【讨论】:

      【解决方案2】:

      看来,问题主要在于处置 XmlWriter 的工作方式 - 如果我使用 XmlWriter.Create 创建它,它在关闭之前不会刷新,因此 StringWriter 是空的。奇怪的是 - 如果我用新的 XmlTextWriter 创建它,它会以某种方式将其内容刷新到 StringWriter,所以我的初始方法工作得很好。

      这次我只需要重新排列一行代码:

          public static string SerializeObject<T>(T serialisable)
          {
              var serializer = new DataContractSerializer(serialisable.GetType());
              using (var writer = new StringWriter())
              {
                  using (var stm = XmlWriter.Create(writer,
                      new XmlWriterSettings()
                      {
                          NewLineHandling = NewLineHandling.Entitize,
                          Encoding = UTF8Encoding.UTF8
                      }))
                  {
                      serializer.WriteObject(stm, serialisable);
                      // <- previously writer.ToString() was here and I got an empty string
                  }     
      
                  return writer.ToString();
              }
          }
      

      现在“\r”字符被正确编码为&amp;#xD;,但“\n”不是。而且编码还是utf-16,虽然我设置为UTF8。我想,这是另一个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-11
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多