Xml序列化与“真”和“假”

时间:2009-07-20 18:47:47

标签: c# xml xml-serialization boolean

我遇到了使用布尔值反序列化XML文件的问题。我正在反序列化的源XML文件是从VB6应用程序创建的,其中所有布尔值都是大写的(TrueFalse)。当我尝试反序列化XML时,我得到了一个

System.FormatException: The string 'False' is not a valid Boolean value.

有没有办法说使用属性忽略大小写?

10 个答案:

答案 0 :(得分:5)

根据another stack overflow question,你可以这样做:

public class MySerilizedObject
{
    [XmlIgnore]
    public bool BadBoolField { get; set; }

    [XmlElement("BadBoolField")]
    public string BadBoolFieldSerialize
    {
        get { return this.BadBoolField ? "True" : "False"; }
        set
        {
            if(value.Equals("True"))
                this.BadBoolField = true;
            else if(value.Equals("False"))
                this.BadBoolField = false;
            else
                this.BadBoolField = XmlConvert.ToBoolean(value);
        }
    }
}

答案 1 :(得分:4)

您可以将该值作为字符串读入字符串字段,然后使用readonly bool字段,其中包含if语句以返回bool true或false。

例如(使用c#):

public bool str2bool(string str)
{
  if (str.Trim().ToUpper() == "TRUE")
      return true;
  else
      return false;
}

您可以在模板中使用它:

<xsl:if test="user:str2bool($mystr)">

答案 2 :(得分:4)

使用0或1代替使用True或False。它适用于布尔值。

答案 3 :(得分:3)

没有。 XML Serializer使用XML Schema,“True”和“False”不是有效的布尔值。

您可以使用XML转换来转换这两个值,也可以实现IXmlSerializable接口并自行进行序列化和反序列化。

答案 4 :(得分:2)

根据我发现的其他一些问题,我提出了一个更清洁的解决方案。它更清晰,因为你不需要代码中的任何东西,除了将类型声明为SafeBool,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
 <java version="1.8.0_112" class="java.beans.XMLDecoder">
 <object class="simple.Simple">
  <void property="n">
   <int>7</int>
  </void>
 </object>
</java>

你甚至可以让它们成为可选的,一切正常。此SafeBool结构将处理true / false,yes / no或y / n的任何case变体。它将始终序列化为true / false,但是我有其他类似于此的结构,当模式需要时(例如:BoolYN,BoolYesNo结构),我使用它来专门序列化为y / n或yes / no。

public class MyXMLClass
{
    public SafeBool Bool { get; set; }
    public SafeBool? OptionalBool { get; set; }
}

答案 5 :(得分:2)

我有一个包含许多布尔值的xml,并且我不想最终拥有这么多重复的布尔值属性,所以我尝试了一种不同的方法来提供自定义xml读取器来完成工作:

public class MyXmlReader : XmlTextReader
{
    public MyXmlReader(TextReader reader) : base(reader) { }
    public override string ReadElementString()
    {
        var text = base.ReadElementString();

        // bool TryParse accepts case-insensitive 'true' and 'false'
        if (bool.TryParse(text, out bool result))
        {
            text = XmlConvert.ToString(result);
        }

        return text;
    }
}

并用于:

using (var sr = new StringReader(text))
using (var r = new MyXmlReader(sr))
{
    var result = serializer.Deserialize(r);
}

答案 6 :(得分:1)

我不认为有。您可以通过将ignoreCase值设置为true来使其成为字符串并进行比较(String.Compare)

答案 7 :(得分:0)

我偶然发现同样的问题,根据jman的回答,我这样解决了:

    [XmlIgnore]
    public bool BadBoolField { get; set; }

    [XmlAttribute("badBoolField")]
    public string BadBoolFieldSerializable
    {
        get
        {
            return this.BadBoolField.ToString();
        }
        set
        {
            this.BadBoolField= Convert.ToBoolean(value);
        }
    }

请注意,这不一定是XML /序列化规范,但它运行良好,它可以处理广泛的转换值(即字符串如“True”,“true”,如果你要替换为字符串的约束它也可以处理数字。)

答案 8 :(得分:0)

在特殊情况下,有一个非常简单和简短的解决方案。

我今天遇到了类似的问题,外部给定的XML文件包含值TRUE / FALSE,这些值应该具有布尔意义。

如果某个应用程序不强制要求反序列化文档包含本机bool,但它只是将其反序列化为受限于任何两个替代值的东西,那么可以简单地使用枚举(这里以属性为例):

public enum BOOL {FALSE, TRUE};

public MyClass
{
    [XmlAttribute]
    public BOOL MyStrangeBooleanAttribute {get; set;}
}

这只是反序列化而没有像这样的元素

的任何问题
<MyClass MyStrangeBooleanAttribute = "TRUE" />

当然,不可能在代码中使用属性来进行直接布尔操作,比如

if (MyStrangeBooleanAttribute) // ... doesn't work

我认为通过定义隐式转换可能有可能解决这个问题,但我还没有对其进行测试,因为我不需要它。

答案 9 :(得分:-1)

不要费心修复破碎的xml系统或打击XmlSerializer,特别是对于那些微不足道的事情。这不值得。 VB6不会很快回来。

相反,在反序列化之前获取文档并更改值。如果您担心在标签之外更改它们,请使用正则表达式或在值中包含尖括号。

    xml = xml.Replace("True", "true").Replace("False", "false");

它不会因为优雅而赢得任何奖项,但它会让你重新开始工作。有时你只需要蓝领。

至于性能,是的,你通过字符串O(n)重复,但由于替换字符串的长度相同,所以它不需要任何移动的字符串元素。此外,根据实现,修改XmlSerializer可能会有更大的开销。