我正在尝试序列化然后反序列化一个对象。序列化工作正常,但反序列化会抛出
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; }
}
答案 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>