2012-03-12 52 views
6

考慮下面的XML:將XML反序列與空元素

<a> 
    <b>2</b> 
    <c></c> 
</a> 

我需要這個XML序列化的對象。所以,我寫了下面的課。

public class A 
{ 
    [XmlElement("b", Namespace = "")] 
    public int? B { get; set; } 

    [XmlElement("c", Namespace = "")] 
    public int? C { get; set; } 

} 

由於我使用nullables,我期待的是,deserialing上述XML時,我會得到一個對象有一個空Ç財產。

取而代之的是,我得到一個異常告訴了的文件有誤。

+0

是*不*空。它是一個零長度的字符串。 – 2012-03-12 18:59:15

+0

請不要在「C#」前加前綴。這就是標籤的用途。 – 2012-03-12 20:33:53

回答

7

缺失元素和無效元素之間存在差異。

甲缺少的元素,<a><b>2</b></a>。如果沒有明確的默認這裏C將帶您指定的任何默認值,使用默認值屬性,或者爲null。

空元件<a><b>2</b><c xs:Nil='true'/></a>。在這裏你會得到空。

當你做<a><b>2</b><c></c><a/> XML序列化器將嘗試解析的String.Empty作爲一個整數的將正確失敗。

由於您的提供商產生無效的XML,你需要做到這一點,如果使用XmlSerializer:

[XmlRoot(ElementName = "a")] 
public class A 
{ 
    [XmlElement(ElementName = "b")] 
    public int? B { get; set; } 

    [XmlElement(ElementName = "c")] 
    public string _c { get; set; } 

    public int? C 
    { 
     get 
     { 
      int retval; 

      return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?) retval : null; 
     } 
    } 
} 

或略好使用的DataContractSerializer

[DataContract(Name="a")] 
public class A1 
{ 
    [DataMember(Name = "b")] 
    public int? B { get; set; } 

    [DataMember(Name = "c")] 
    private string _c { get; set; } 

    public int? C 
    { 
     get 
     { 
      int retval; 

      return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?)retval : null; 
     } 
    } 
} 

雖然DataContractSerializer的不支持屬性如果這是一個問題。

+0

感謝您的信息。我知道你在告訴我什麼。但我沒有控制xml數據(它來自外部服務)。而服務隊提供者正在返回時,實際上它應該返回的xs:無=「真」,所以我必須解決這個問題。 – 2012-03-12 19:08:54

+0

你將需要使C字符串,然後有一個包裝屬性,解析反序列化的字符串爲int?按要求。 – Phil 2012-03-12 19:11:31

+0

謝謝。你的測試不應該是「Strng.IsNullOrEmpty」而不是「IsNullOrWhiteSpace」嗎?你不需要執行cast(int?)retval。然而,爲了避免編譯錯誤,我們需要強制轉換(int?)null – 2012-03-13 10:44:51

1

要在你的例子反序列化空的標籤,如 'C':

<foo> 
     <b>2</b> 
     <c></c> 
    </foo> 

我用這種方法。首先,它使用LINQ從XML文件中刪除空元素或空元素,然後將新文檔反序列化爲Foo類中沒有空或空標記的新文檔。

public static Foo ReadXML(string file) 
    { 
      Foo foo = null; 
      XDocument xdoc = XDocument.Load(file); 
      xdoc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove(); 

      XmlSerializer xmlSer = new XmlSerializer(typeof(Foo)); 
      using (var reader = xdoc.Root.CreateReader()) 
      { 
       foo = (Foo)xmlSer.Deserialize(reader); 
       reader.Close(); 
      } 
      if (foo == null) 
       foo = new Foo(); 

      return foo; 
    } 

這將給你缺省的屬性的默認值。

foo.b = 2; 
    foo.c = 0; //for example, if it's an integer 

我加入了信息從這個鏈接

Remove empty XML tags

Use XDocument as the source for XmlSerializer.Deserialize?

+0

爲什麼不'xdoc.Descendants()。哪裏(e => e.IsEmpty || String.IsNullOrWhiteSpace(e.Value))'? – stomy 2017-11-27 20:53:50

+0

你也可以用'(TextReader reader = new StringReader(xdoc.ToString()))'來代替。 – stomy 2017-11-27 20:55:37