我遇到了使用布尔值反序列化XML文件的问题。我正在反序列化的源XML文件是从VB6应用程序创建的,其中所有布尔值都是大写的(True
,False
)。当我尝试反序列化XML时,我得到了一个
System.FormatException: The string 'False' is not a valid Boolean value.
有没有办法说使用属性忽略大小写?
答案 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可能会有更大的开销。