2016-10-24 61 views
0

我試圖序列化並反序列化一個對象。序列化工作正常,但反序列化拋出一個對對象進行序列化和反序列化(XML文檔(0,0)中存在錯誤。)

System.InvalidOperationException : There is an error in XML document (1, 1). 
    ----> System.Xml.XmlException : Data at the root level is invalid. Line 1, position 1. 

序列化的XML看起來不錯:

<?xml version="1.0" encoding="utf-16"?> 
<Data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Id="1" Status="OK" xmlns="http://biz.si/Project/v0100/Data.xsd"> 
    <DataGroup Type="SomeType">AAEC</DataGroup> 
</Data> 

編碼是UTF-16,這是確定的,但我懷疑有反序列化過程中的編碼問題。現在代碼在測試環境(單元測試)中運行,但序列化的XML將被髮送到Web服務。

這是我的代碼:

[TestFixture] 
public class Foobar 
{ 
    [Test] 
    public void Test() 
    { 
     var d = new Data 
     { 
      Id = "1", 
      Status = "OK", 
      DataGroup = new DataGroup 
      { 
       Type = "SomeType", 
       Value = new byte[] { 0x00, 0x01, 0x02 } 
      } 
     }; 

     var serialized = Serialize(d); 
     var deserialized = Deserialize(serialized); // exception is thrown here. 

     Debug.WriteLine("ok"); 
    } 

    private XmlNode Serialize(Data data) 
    { 
     XmlSerializer xsSubmit = new XmlSerializer(typeof(Data)); 
     StringWriter sww = new StringWriter(); 
     using (XmlWriter writer = XmlWriter.Create(sww)) 
     { 
      xsSubmit.Serialize(writer, data); 
      var xml = sww.ToString(); 
      var xmlDocument = new XmlDocument(); 
      xmlDocument.LoadXml(xml); 
      return xmlDocument; 
     } 
    } 

    private Data Deserialize(XmlNode xmlData) 
    { 
     XmlSerializer xmlSerializer = new XmlSerializer(typeof(Data)); 
     MemoryStream memoryStream = new MemoryStream(Encoding.Default.GetBytes(xmlData.InnerText)); 
     return (Data)xmlSerializer.Deserialize(memoryStream); 
    } 
} 

[XmlRoot(Namespace = "http://biz.si/Project/v0100/Data.xsd", IsNullable = false)] 
[XmlType(AnonymousType = true)] 
public class Data 
{ 
    [XmlAttribute] 
    public string Id { get; set; } 

    [XmlAttribute] 
    public string Status { get; set; } 

    [XmlElement("DataGroup")] 
    public DataGroup DataGroup { get; set; } 
} 

[XmlType(AnonymousType = true)] 
public class DataGroup 
{ 
    [XmlAttribute] 
    public string Type { get; set; } 

    [XmlText(DataType = "base64Binary")] 
    public byte[] Value { get; set; } 
} 

回答

2

兩個問題在這裏:InnerText是不是你想要的屬性。它根本不是XML;在調試器中查看它。其次,不要使用MemoryStream;無論你得到那一個,他只是在拖着你。 StringReader更容易工作。

private Data Deserialize(XmlNode xmlData) 
{ 
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Data)); 
    using (var stream = new StringReader(xmlData.OuterXml)) 
    { 
     return (Data)xmlSerializer.Deserialize(stream); 
    } 
} 
0

這是我的經驗.NET XML序列化不喜歡它,也不允許序列化類沒有參數的構造函數,但你看要能。以下是我如何做所有的XML序列化。我跑你的類,並序列化和反序列化工作正常。你可以調整它以滿足你的需求。我的測試代碼在課程代碼之後。

[XmlRoot(Namespace = "http://biz.si/Project/v0100/Data.xsd", IsNullable = false)] 
    [XmlType(AnonymousType = true)] 
    public class sventevitData 
    { 
    [XmlAttribute] 
    public string Id { get; set; } 

    [XmlAttribute] 
    public string Status { get; set; } 

    [XmlElement("DataGroup")] 
    public DataGroup DataGroup { get; set; } 


    /// <summary> 
    /// Initializes a new instance of the <see cref="sventevitData"/> class. 
    /// Parameterless constructor required for .NET XML serialization 
    /// </summary> 
    public sventevitData(){} 

    public void SerializeData(String FileWithPath) 
    { 
     try 
     { 
     using(Stream stream = new FileStream( FileWithPath,  FileMode.Create, 
               FileAccess.Write, FileShare.Write)) 
     { 
      // Serialize into the storage medium 
      XmlSerializer xmlserial = new XmlSerializer(typeof(sventevitData)); 
      xmlserial.Serialize(stream, this); 
      stream.Close(); 
     } 
     } 
     catch(Exception ex) 
     { 
     string msg = ex.Message; 
     ex = ex.InnerException; 

     while(ex != null) 
     { 
      msg += "" + ex.Message; 
      ex = ex.InnerException; 
     } 

     System.Windows.Forms.MessageBox.Show( 
      String.Format("Exception writing sventevitData {0}: {1}", 
          FileWithPath, msg)); 
     } 
    } 


    public static sventevitData DeserializeData(String FileWithPath) 
    { 
     sventevitData tmp; 
     Stream stream; 

     try 
     { 
     // Read the file back into a stream 
     if(!File.Exists(FileWithPath)) 
     { 
      DirectoryInfo di = null; 

      if(!Directory.Exists(Path.GetDirectoryName(FileWithPath))) 
      { 

      AddDirSecurity(Path.GetDirectoryName(FileWithPath), 
          System.Security.Principal.WindowsIdentity.GetCurrent().Name, 
          FileSystemRights.Write, AccessControlType.Allow); 

      di = Directory.CreateDirectory(Path.GetDirectoryName(FileWithPath)); 
      } 

      AddDirSecurity(FileWithPath, System.Security.Principal.WindowsIdentity.GetCurrent().Name, 
           FileSystemRights.Write, AccessControlType.Allow); 

      File.Create(FileWithPath); 
     } 

     using(stream = new FileStream(FileWithPath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      // Now create a binary formatter 
      XmlSerializer xmlserializer = new XmlSerializer(typeof(sventevitData)); 
      stream = new FileStream(FileWithPath, FileMode.Open, FileAccess.Read, FileShare.Read); 
      tmp = (sventevitData)xmlserializer.Deserialize(stream); 
      stream.Close(); 

      // Deserialize the object and use it 
      return tmp; 
     } 
     } 
     catch(Exception ex) 
     { 
     string msg = ex.Message; 
     ex = ex.InnerException; 

     while(ex != null) 
     { 
      msg += "" + ex.Message; 
      ex = ex.InnerException; 
     } 

     System.Windows.Forms.MessageBox.Show(String.Format("Exception reading {0}: {1}", FileWithPath, msg)); 
     } 

     return new sventevitData(); 
    } 


    private static void AddDirSecurity( String Dir, 
              String Account, 
              FileSystemRights Rights, 
              AccessControlType AccessType) 
    { 
     // Create a new DirectoryInfo object. 
     DirectoryInfo dInfo = new DirectoryInfo(Dir); 

     // Get a DirectorySecurity object that represents the 
     // current security settings. 
     DirectorySecurity dSecurity = dInfo.GetAccessControl(); 

     // Add the FileSystemAccessRule to the security settings. 
     dSecurity.AddAccessRule(new FileSystemAccessRule(Account, Rights, AccessType)); 

     // Set the new access settings. 
     dInfo.SetAccessControl(dSecurity); 
    } 
    } 

    [XmlType(AnonymousType = true)] 
    public class DataGroup 
    { 
    [XmlAttribute] 
    public string Type { get; set; } 

    [XmlText(DataType = "base64Binary")] 
    public byte[] Value { get; set; } 
    } 

[TestClass] 
    public class sventevitDataTest 
    { 
    [TestMethod] 
    [TestCategory("StackOverflow")] 
    public void SerializeTest() 
    { 
     string fileWithPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; 
     fileWithPath  = Path.Combine(fileWithPath, "testData.xml"); 

     sventevitData data = new sventevitData(); 

     data.Id   = "1"; 
     data.Status  = "OK"; 
     data.DataGroup = new DataGroup() 
     { 
     Type = "SomeType", 
     Value = new byte[]{ 0x00, 0x01, 0x02 } 
     }; 

     data.SerializeData(fileWithPath); 
    } 


    [TestMethod] 
    [TestCategory("StackOverflow")] 
    public void DeserializeTest() 
    { 
     string fileWithPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; 
     fileWithPath  = Path.Combine(fileWithPath, "testData.xml"); 

     sventevitData data = sventevitData.DeserializeData(fileWithPath); 
    } 
    } 

忘記以包括XML

<?xml version="1.0"?> 
<sventevitData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Id="1" Status="OK" xmlns="http://biz.si/Project/v0100/Data.xsd"> 
    <DataGroup Type="SomeType">AAEC</DataGroup> 
</sventevitData> 
+1

沒有定義的構造A C#類都有一個默認構造函數,它是無參數(授予有趣的情況下的基類沒有公共參數構造函數)。這就是爲什麼他「似乎能夠」序列化一個「似乎」沒有無參數構造函數的類。注意他的'Test()'方法創建了一個沒有任何構造函數參數的'Data' *實例:'var d = new Data {};'。這是一個無參數的構造函數。 –

+1

謝謝你的信息埃德!我喜歡學習新事物。 – DB9

相關問題