2009-07-20 36 views
12

Tôi gặp sự cố với việc deserializing một tệp XML có các giá trị boolean. Các tệp XML nguồn tôi đang deserializing đã được tạo ra từ một ứng dụng VB6, trong đó tất cả các giá trị boolean được viết hoa (True, False). Khi tôi cố gắng deserialize XML, tôi nhận được mộtNối tiếp Xml so với "Đúng" và "Sai"

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

Có cách nào để nói bỏ qua trường hợp với một thuộc tính?

Trả lời

5

Bạn có thể đọc giá trị đó dưới dạng chuỗi thành trường chuỗi, sau đó có trường bool chỉ đọc có câu lệnh if trong đó để trả về giá trị bool true hoặc false.

Ví dụ (sử dụng C#):

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

Và bạn có thể sử dụng nó trong các mẫu:

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

Bạn nên bao gồm một ví dụ về điều này. Bạn có thể đã có gợi ý tốt nhất nếu bạn làm. –

1

Tôi không nghĩ là có. Bạn có thể làm cho nó chuỗi và làm một so sánh (String.Compare) bằng cách đặt giá trị ignoreCase thành true.

3

Không có. Trình nối tiếp XML hoạt động với Lược đồ XML, và "Đúng" và "Sai" không phải là các boolean hợp lệ.

Bạn có thể sử dụng Chuyển đổi XML để chuyển đổi hai giá trị này hoặc bạn có thể triển khai giao diện IXmlSerializable và thực hiện tuần tự hóa và tự tuần tự hóa.

+0

bạn đúng John, đó là những gì xảy ra khi bạn trả lời trước khi ăn trưa: \ .. nhưng công bằng đề nghị của bạn về Xml Transform cũng có khả năng biến đổi một giá trị không phải là boolean. –

+0

Thực ra, không. Tôi sẽ có anh ta chỉ tham khảo một cách rõ ràng các thuộc tính và/hoặc các phần tử boolean. Tôi không có ý định biến đổi mọi thuộc tính. –

+0

Đã hiểu John. –

5

Thay vì sử dụng Đúng hay Sai, sử dụng 0 hoặc 1. Nó sẽ làm việc cho Boolean.

4

Dựa trên another stack overflow question bạn có thể làm:

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

tôi stumbled khi cùng một vấn đề, và dựa trên các câu trả lời bằng jman, tôi giải quyết nó theo cách này:

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

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

Hãy nhận biết đây là không nhất thiết là đặc tả XML/Serialization, nhưng nó hoạt động tốt và nó có thể xử lý một giá trị chuyển đổi phổ biến (tức là chuỗi như "True", "true", nếu bạn thay thế ràng buộc là chuỗi nó có thể xử lý số).

0

Đây là giải pháp sạch hơn tôi đã đưa ra dựa trên một số câu hỏi khác mà tôi đã tìm thấy. Nó là rất sạch vì sau đó bạn không cần phải bất cứ điều gì trong mã của bạn ngoại trừ khai báo kiểu như SafeBool, như thế này:

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

bạn thậm chí có thể làm cho họ không bắt buộc và tất cả chỉ hoạt động. Cấu trúc SafeBool này sẽ xử lý bất kỳ biến thể nào của true/false, yes/no hoặc y/n. Nó sẽ luôn luôn tuần tự hóa thành true/false, tuy nhiên tôi có các cấu trúc khác tương tự như tôi sử dụng để tuần tự hóa cụ thể là y/n hoặc có/không khi lược đồ yêu cầu (ví dụ: BoolYN, BoolYesNo structs).

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

Xem tìm kiếm của tôi và thay thế câu trả lời. Bạn có rất nhiều mã có thể có O (n) tốt hơn, nhưng đôi khi vấn đề chỉ cần một giải pháp Ross Perot. mở mui xe và sửa chữa nó. –

-1

Đừng bận tâm sửa chữa hệ thống xml bị hỏng hoặc chiến đấu với XmlSerializer, đặc biệt là đối với một cái gì đó tầm thường. Nó không đáng. VB6 không quay trở lại bất cứ lúc nào sớm.

Thay vào đó, hãy giữ tài liệu trước khi được deserialized và thay đổi các giá trị. Nếu bạn lo lắng về việc thay đổi chúng bên ngoài các thẻ, sau đó sử dụng cụm từ thông dụng hoặc bao gồm dấu ngoặc nhọn trong các giá trị.

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

Nó sẽ không giành được bất kỳ giải thưởng nào cho sự sang trọng, nhưng nó giúp bạn trở lại làm việc. Đôi khi bạn chỉ cần có màu xanh cổ áo nó.

Đối với hiệu suất, có, bạn đang nhắc lại thông qua chuỗi O (n), nhưng vì chuỗi thay thế có cùng độ dài, nên không yêu cầu bất kỳ phần tử chuỗi di chuyển nào xung quanh. Hơn nữa, tùy thuộc vào việc thực hiện, có thể có một chi phí lớn hơn trong việc sửa đổi XmlSerializer.

+0

Bạn giả sử bạn có quyền truy cập dễ dàng vào HTML gốc để có thể thực hiện tìm kiếm và thay thế, vì vậy câu trả lời của bạn không phải là câu trả lời hay. Chưa kể nếu gói XML lớn, mã của bạn sẽ tạo ra một chuỗi tạm thời khổng lồ hai lần, bởi vì các chuỗi trong .net là không thay đổi. –

+0

@KendallBennett Bạn cũng không cho rằng mình có quyền truy cập vào các lớp học? Tôi chưa bao giờ thấy một trường hợp mà bạn có thể deserialize dữ liệu mà không có quyền truy cập vào đầu vào xml. Nếu bạn thực sự lo lắng về hiệu suất và bộ nhớ, bạn thực sự nên tránh sử dụng XmlSerializer vì nó sử dụng sự phản chiếu, một trong những hoạt động tốn kém nhất trong .NET. Không có gì về giải pháp của tôi nói rằng nó không thể làm việc trên streaming dữ liệu. Quan điểm của tôi là triển khai ngây thơ đôi khi là những cách tốt nhất. Tôi đã học được điều này. –

+0

Bạn không thể đơn giản chặn tất cả mọi thứ trong XML đúng với Sai và sai. Nó chắc chắn là ngây thơ và chắc chắn sẽ phá vỡ một số loại phản ứng. Điều gì sẽ xảy ra nếu có thứ gì đó được lưu trữ trong đó có phân biệt chữ hoa chữ thường và có chữ True trong đó không? Đột nhiên mà không còn hoạt động ... –

Các vấn đề liên quan