使用XmlSerializer反序列化XML时,如何保留只包含空格的元素内容?

8

我有一个类InputConfig,其中包含一个List<IncludeExcludeRule>:

public class InputConfig
{
    // The rest of the class omitted 
    private List<IncludeExcludeRule> includeExcludeRules;
    public List<IncludeExcludeRule> IncludeExcludeRules
    {
        get { return includeExcludeRules; }
        set { includeExcludeRules = value; }
    }
}

public class IncludeExcludeRule
{
    // Other members omitted
    private int idx;
    private string function;

    public int Idx
    {
        get { return idx; }
        set { idx = value; }
    }

    public string Function
    {
        get { return function; }
        set { function = value; }
    }
}

Using ...

FileStream fs = new FileStream(path, FileMode.Create);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(InputConfig));
xmlSerializer.Serialize(fs, this);
fs.Close();

... and ...

StreamReader sr = new StreamReader(path);
XmlSerializer reader = new XmlSerializer(typeof(InputConfig));
InputConfig inputConfig = (InputConfig)reader.Deserialize(sr);

它的工作方式像一位冠军!很容易,除了我需要在反序列化时保留成员function中的空格。生成的XML文件表明在序列化时保留了空格,但在反序列化时丢失了。

<IncludeExcludeRules>
  <IncludeExcludeRule>
    <Idx>17</Idx>
    <Name>LIEN</Name>
    <Operation>E =</Operation>
    <Function>  </Function>
  </IncludeExcludeRule>
</IncludeExcludeRules>
XmlAttributeAttribute 的 MSDN 文档似乎在“Remarks”部分解决了这个问题,但我不知道如何使用它。它提供以下示例:
// Set this to 'default' or 'preserve'.
[XmlAttribute("space", 
Namespace = "http://www.w3.org/XML/1998/namespace")]
public string Space 

啥?将什么设置为“default”或“preserve”?我确定我接近正确了,但这似乎毫无意义。我想在成员之前在类中插入一个单行的XmlAttribute以保留反序列化期间的空格。

这里和其他地方有许多类似的问题,但它们似乎都涉及使用XmlReader和XmlDocument,或者深入研究各个节点等。我想避免那种深度。


当您在Function属性上放置[XmlAttribute("space", Namespace = "http://www.w3.org/XML/1998/namespace")]时会发生什么?该属性是否被添加? - Panagiotis Kanavos
加上public string Space ="preserve";之后就可以了。但是我更喜欢使用下面描述的XmlReader/XmlWriter,因为这样我就可以简单地使用注释[XmlAttribute("xml:space=preserve")] - CDTWF
4个回答

9
为了在XML反序列化过程中保留所有空格,请创建并使用一个XmlReader
StreamReader sr = new StreamReader(path);
XmlReader xr = XmlReader.Create(sr);
XmlSerializer reader = new XmlSerializer(typeof(InputConfig));
InputConfig inputConfig = (InputConfig)reader.Deserialize(xr);

XmlSerializer.Deserialize(XmlReader) 不同,XmlSerializer.Deserialize(TextReader) 仅保留由 xml:space="preserve" 属性标记的显着空格。

1
我实际上更喜欢这种方法,因为它比添加一个名为“Space”的字符串成员更有意义。 - CDTWF

5

这份晦涩的文档意味着您需要使用[XmlAttribute("space", Namespace = "http://www.w3.org/XML/1998/namespace")]来指定一个附加字段,其值为defaultpreserve。 XmlAttribute控制字段或属性的生成属性名称。该属性的值是该字段的值。

例如,以下类:

public class Group
{
   [XmlAttribute (Namespace = "http://www.cpandl.com")]
   public string GroupName;

   [XmlAttribute(DataType = "base64Binary")]
   public Byte [] GroupNumber;

   [XmlAttribute(DataType = "date", AttributeName = "CreationDate")]
   public DateTime Today;

   [XmlAttribute("space", Namespace = "http://www.w3.org/XML/1998/namespace")]
   public string Space ="preserve";
}

将被序列化为:

<?xml version="1.0" encoding="utf-16"?>
<Group xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       d1p1:GroupName=".NET" 
       GroupNumber="ZDI=" 
       CreationDate="2001-01-10" 
       xml:space="preserve" 
       xmlns:d1p1="http://www.cpandl.com" />

谢谢,我想知道MSDN文档是否要求我添加一个名为Space的字符串,但决定这没有意义。如果他们的示例更好一点就好了。 - CDTWF

2

迈克尔·刘上面的答案对我有用,但带有一个警告。我原本想在他的答案下发表评论,但我的“声望”不够。

我发现使用XmlReader并不能完全解决这个问题,原因是相关的.net属性具有以下属性:

XmlText(DataType="normalizedString")

为了纠正这个问题,我发现添加额外的属性可以解决:
[XmlAttribute("xml:space=preserve")]

显然,如果您无法控制 .net 类,则会出现问题。

2

我相信你缺失的部分是在字段中添加xml:space="preserve",例如:

<Function xml:space="preserve">   </Function>

更多细节请参考XML规范中的相关章节。

根据MSDN博客中的注释,类定义应该如下:

[XmlAttribute("space=preserve")]

但是我记得它是这样的
[XmlAttribute("xml:space=preserve")]

这将涉及明确编辑我想避免的XML。问题是,如何通过类定义中的注释实现这一点。 - CDTWF
OP正在询问如何使用XmlAttribute属性来实现这一点。 - Panagiotis Kanavos
@pksimeonov,看起来非常合理。添加该注释的结果是,现在XML中的两个空格会导致类成员保持为null,而以前它会将其设置为空字符串。这与人们的预期完全相反。是的,我真的想要那两个空格。 - CDTWF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接