2009-07-20 8 views
12

Ich habe ein Problem mit der Deserialisierung einer XML-Datei mit booleschen Werten. Die Quell-XML-Dateien, die ich deserialisiere, wurden aus einer VB6-Anwendung erstellt, in der alle booleschen Werte groß geschrieben werden (True, False). Wenn ich versuche, die XML deserialisiert, ich bin immer einXml-Serialisierung vs. "True" und "False"

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

Gibt es eine Möglichkeit Fall mit einem Attribut zu sagen, ignorieren?

Antwort

5

Sie könnten diesen Wert als Zeichenfolge in ein Zeichenfolgenfeld lesen und dann ein readonly-bool-Feld mit einer if-Anweisung verwenden, um bool true oder false zurückzugeben.

Zum Beispiel (unter Verwendung von C#):

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

Und Sie es in der Vorlage verwenden können: für

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

Sie sollten ein Beispiel dafür angeben. Sie haben wahrscheinlich den besten Vorschlag, wenn Sie es tun. –

1

Ich glaube nicht, dass es gibt. Sie könnten es string machen und einen Vergleich (String.Compare) durchführen, indem Sie den ignoreCase-Wert auf true setzen.

3

Gibt es nicht. Der XML-Serializer arbeitet mit einem XML-Schema und "True" und "False" sind keine gültigen Booleschen Werte.

Sie könnten entweder eine XML-Transformation verwenden, um diese beiden Werte zu konvertieren, oder Sie können die IXmlSerializable-Schnittstelle implementieren und die Serialisierung und Deserialisierung selbst durchführen.

+0

Sie haben Recht John, das ist, was passiert, wenn Sie vor dem Mittagessen zu beantworten: \ .. aber um fair zu sein Ihr Vorschlag von Xml Transform könnte möglicherweise auch einen Wert, der nicht ein Boolean sein soll. –

+0

Eigentlich nein. Ich würde ihn explizit nur auf die Attribute und/oder Elemente verweisen, die boolesch sind. Ich wollte nicht jedes Attribut umwandeln. –

+0

Verstanden John. –

5

Anstelle der Verwendung von Wahr oder Falsch, verwenden Sie 0 oder 1. Es wird funktionieren Boolesch.

4

Basierend auf another stack overflow question Sie tun können:

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); 
     } 
    } 
} 
0

ich auf das gleiche Problem gestolpert und auf die Antwort von jman basiert, löste ich es so:

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

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

Beachten Sie, dies ist nicht unbedingt nach XML/Serialization-Spezifikation, aber es funktioniert gut und es kann eine weit verbreitete Konvertierung Werte (dh String wie "True", "true", wenn Sie die Einschränkung, eine Zeichenfolge zu sein, könnte auch mit Zahlen umgehen) umgehen.

0

Hier ist eine viel sauberere Lösung, die ich basierend auf einigen anderen Fragen, die ich gefunden habe, kam. Es ist viel sauberer, weil dann nicht wahr, außer in Ihrem Code etwas brauchen die Art, wie SAFEBOOL zu erklären, wie folgt aus:

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

Sie können sogar machen sie optional und es funktioniert einfach. Diese SafeBool-Struktur behandelt alle Fallvarianten von wahr/falsch, ja/nein oder y/n. Es wird immer serialisieren als wahr/falsch, aber ich habe andere Strukturen ähnlich wie ich es verwenden, um speziell als y/n oder ja/nein zu serialisieren, wenn das Schema dies erfordert (zB: BoolYN, BoolYesNo Strukturen).

using System.Xml; 
using System.Xml.Schema; 
using System.Xml.Serialization; 

namespace AMain.CommonScaffold 
{ 
    public struct SafeBool : IXmlSerializable 
    { 
     private bool _value; 

     /// <summary> 
     /// Allow implicit cast to a real bool 
     /// </summary> 
     /// <param name="yn">Value to cast to bool</param> 
     public static implicit operator bool(
      SafeBool yn) 
     { 
      return yn._value; 
     } 

     /// <summary> 
     /// Allow implicit cast from a real bool 
     /// </summary> 
     /// <param name="b">Value to cash to y/n</param> 
     public static implicit operator SafeBool(
      bool b) 
     { 
      return new SafeBool { _value = b }; 
     } 

     /// <summary> 
     /// This is not used 
     /// </summary> 
     public XmlSchema GetSchema() 
     { 
      return null; 
     } 

     /// <summary> 
     /// Reads a value from XML 
     /// </summary> 
     /// <param name="reader">XML reader to read</param> 
     public void ReadXml(
      XmlReader reader) 
     { 
      var s = reader.ReadElementContentAsString().ToLowerInvariant(); 
      _value = s == "true" || s == "yes" || s == "y"; 
     } 

     /// <summary> 
     /// Writes the value to XML 
     /// </summary> 
     /// <param name="writer">XML writer to write to</param> 
     public void WriteXml(
      XmlWriter writer) 
     { 
      writer.WriteString(_value ? "true" : "false"); 
     } 
    } 
} 
+0

Sehen Sie meine Suche und ersetzen Sie die Antwort. Sie haben eine Menge Code, der möglicherweise besser O (n) hat, aber manchmal erfordert das Problem nur eine Ross-Perot-Lösung. öffne die Haube und repariere sie. –

-1

Kümmern Sie sich nicht ein gebrochenes xml-System oder kämpfen XmlSerializer, vor allem für etwas so trivial zu fixieren. Es lohnt sich nicht. VB6 kommt nicht so bald zurück.

Greifen Sie stattdessen auf das Dokument zu, bevor es deserialisiert wird, und ändern Sie die Werte. Wenn Sie Bedenken haben, sie außerhalb der Tags zu ändern, verwenden Sie reguläre Ausdrücke oder schließen Sie die spitzen Klammern in die Werte ein.

Es wird keine Auszeichnung für Eleganz gewinnen, aber es bringt Sie zurück zur Arbeit. Manchmal muss man es nur blue kragen.

Für die Leistung, ja, wiederholen Sie durch die Zeichenfolge O (n), aber da die Ersatzzeichenfolgen die gleiche Länge haben, erfordert es keine beweglichen Zeichenfolgenelemente um. Abhängig von der Implementierung kann außerdem ein größerer Aufwand beim Ändern von XmlSerializer entstehen.

+0

Sie gehen davon aus, dass Sie einfachen Zugriff auf den ursprünglichen HTML-Code haben, um eine Suche durchführen und ersetzen zu können, sodass Ihre Antwort nicht gut ist. Nicht zu vergessen, wenn das XML-Paket groß ist, wird Ihr Code eine riesige temporäre Zeichenfolge zweimal erzeugen, da Strings in .net unveränderlich sind. –

+0

@KendallBennett Nimmst du nicht auch an, dass er Zugang zu den Klassen hat? Ich habe noch nie einen Fall gesehen, in dem Sie Daten deserialisieren können, ohne Zugriff auf die XML-Eingabe zu haben. Wenn Sie wirklich an Leistung und Speicher interessiert sind, sollten Sie XmlSerializer wirklich vermeiden, da es Reflektion verwendet, die eine der teuersten Operationen in .NET ist. Es gibt nichts über meine Lösung, die sagt, dass es nicht an Streaming-Daten arbeiten kann. Mein Punkt ist, dass naive Implementierungen manchmal die besten sind. Ich habe das auf dem Hardway gelernt. –

+0

Sie können nicht einfach alles ersetzen in der XML, die True mit True und False mit False ist. Es ist sicherlich naiv und wird sicherlich einige Arten von Antworten brechen. Was, wenn da etwas gespeichert war, das die Groß- und Kleinschreibung berücksichtigte und das Wort Wahr darin hatte? Plötzlich funktioniert das nicht mehr ... –