序列化和反序列化对象(XML文档(0,0)中存在错误。)

时间:2016-10-24 13:34:05

标签: c# .net xml serialization encoding

我正在尝试序列化然后反序列化一个对象。序列化工作正常,但反序列化会抛出

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 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分: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>