C# XML 序列化 - 前导问号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/660440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 12:17:15  来源:igfitidea点击:

C# XML Serialization - Leading Question Marks

c#xml-serialization

提问by

Problem

问题

By leveraging some samples I found online here, I've written some XML serialization methods.

通过利用一些样品我在网上找到这里,我已经写了一些XML序列化的方法。

  • Method1:Serialize an Object and return: (a) the type, (b) the xml string
  • Method2:Takes (a) and (b) above and gives you back the Object.
  • 方法一:序列化一个对象并返回:(a)类型,(b)xml字符串
  • 方法 2:采用上面的 (a) 和 (b) 并将对象返回给您。

I noticed that the xml string from the Method1contains a leading '?'. This seems to be fine when using Method2to reconstruct the Object.

我注意到Method1中的 xml 字符串包含一个前导“?”。这在使用Method2重建对象时似乎没问题。

But when doing some testing in the application, sometimes we got leading '???' instead. This caused the Method2to throw an exception while trying to reconstruct the Object. The 'Object' in this case was just a simple int.

但是在应用程序中进行一些测试时,有时我们会领先'???' 反而。这导致Method2在尝试重建对象时抛出异常。在这种情况下,“对象”只是一个简单的整数。

System.InvalidOperationException was unhandled Message="There is an error in XML document (1, 1)." Source="System.Xml" StackTrace: at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream) at XMLSerialization.Program.DeserializeXmlStringToObject(String xmlString, String objectType) in C:\Documents and Settings\...Projects\XMLSerialization\Program.cs:line 96 at XMLSerialization.Program.Main(String[] args) in C:\Documents and Settings\...Projects\XMLSerialization\Program.cs:line 49
" System.InvalidOperationException was unhandled Message="XML 文档 (1, 1) 中存在错误。" Source="System.Xml" StackTrace: 在 System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at System.Xml .Serialization.XmlSerializer.Deserialize(Stream stream) at XMLSerialization.Program.DeserializeXmlStringToObject(String xmlString, String objectType) in C:\Documents and Settings\...Projects\XMLSerialization\Program.cs:line 96 at XMLSerialization.Program.Main (String[] args) 在 C:\Documents and Settings\...Projects\XMLSerialization\Program.cs:line 49

Would anyone be able to shed some light on what might be causing this?

任何人都可以阐明可能导致这种情况的原因吗?

Sample Code

示例代码

Here's sample code from the mini-tester I wrote while coding this up which runs as a VS console app. It'll show you the XML string. You can also uncomment the regions to append the extra leading '??' to reproduce the exception.

这是我在编写代码时编写的迷你测试器的示例代码,它作为 VS 控制台应用程序运行。它会向您显示 XML 字符串。您还可以取消注释区域以附加额外的前导“??” 重现异常。



using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace XMLSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            // deserialize to string
            #region int
            object inObj = 5;
            #endregion

            #region string
            //object inObj = "Testing123";
            #endregion

            #region list
            //List inObj = new List();
            //inObj.Add("0:25");
            //inObj.Add("1:26");
            #endregion

            string[] stringArray = SerializeObjectToXmlString(inObj);

            #region include leading ???
            //int indexOfBracket = stringArray[0].IndexOf('<');
            //stringArray[0] = "??" + stringArray[0];
            #endregion

            #region strip out leading ???
            //int indexOfBracket = stringArray[0].IndexOf('<');
            //string trimmedString = stringArray[0].Substring(indexOfBracket);
            //stringArray[0] = trimmedString;
            #endregion

            Console.WriteLine("Input");
            Console.WriteLine("-----");
            Console.WriteLine("Object Type: " + stringArray[1]);
            Console.WriteLine();
            Console.WriteLine("XML String: " + Environment.NewLine + stringArray[0]);
            Console.WriteLine(String.Empty);

             // serialize back to object
            object outObj = DeserializeXmlStringToObject(stringArray[0], stringArray[1]);

            Console.WriteLine("Output");
            Console.WriteLine("------");

            #region int
            Console.WriteLine("Object: " + (int)outObj);
            #endregion

            #region string
            //Console.WriteLine("Object: " + (string)outObj);
            #endregion

            #region list
            //string[] tempArray;
            //List list = (List)outObj;

            //foreach (string pair in list)
            //{
            //    tempArray = pair.Split(':');
            //    Console.WriteLine(String.Format("Key:{0} Value:{1}", tempArray[0], tempArray[1]));
            //}
            #endregion

            Console.Read();
        }

        private static string[] SerializeObjectToXmlString(object obj)
        {
            XmlTextWriter writer = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);

            MemoryStream stream = (MemoryStream)writer.BaseStream;
            string xmlString = UTF8ByteArrayToString(stream.ToArray());

            string objectType = obj.GetType().FullName;

            return new string[]{xmlString, objectType};
        }

        private static object DeserializeXmlStringToObject(string xmlString, string objectType)
        {
            MemoryStream stream = new MemoryStream(StringToUTF8ByteArray(xmlString));
            XmlSerializer serializer = new XmlSerializer(Type.GetType(objectType));

            object obj = serializer.Deserialize(stream);

            return obj;
        }

        private static string UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetString(characters);
        }

        private static byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetBytes(pXmlString);
        } 


    }
}


回答by Dan Herbert

When I've come across this before, it usually had to do with encoding. I'd try specifying the encoding when you serialize your object. Try using the following code. Also, is there any specific reason why you need to return a string[]array? I've changed your methods to use generics so you don't have to specify a type.

当我以前遇到过这个时,它通常与编码有关。当您序列化对象时,我会尝试指定编码。尝试使用以下代码。另外,是否有任何特定原因需要返回string[]数组?我已将您的方法更改为使用泛型,因此您不必指定类型。

private static string SerializeObjectToXmlString<T>(T obj)
{
    XmlSerializer xmls = new XmlSerializer(typeof(T));
    using (MemoryStream ms = new MemoryStream())
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Encoding = Encoding.UTF8;
        settings.Indent = true;
        settings.IndentChars = "\t";
        settings.NewLineChars = Environment.NewLine;
        settings.ConformanceLevel = ConformanceLevel.Document;

        using (XmlWriter writer = XmlTextWriter.Create(ms, settings))
        {
            xmls.Serialize(writer, obj);
        }

        string xml = Encoding.UTF8.GetString(ms.ToArray());
        return xml;
    }
}

private static T DeserializeXmlStringToObject <T>(string xmlString)
{
    XmlSerializer xmls = new XmlSerializer(typeof(T));

    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
    {
        return (T)xmls.Deserialize(ms);
    }
}

If you still have problems, try using Encoding.ASCIIin your code anywhere you see Encoding.UTF8, unless you have a specific reason for using UTF8. I'm not sure of the cause, but I've seen UTF8 encoding cause this exact problem in certain cases when serializing.

如果您仍然有问题,请尝试Encoding.ASCII在您看到的任何地方使用代码Encoding.UTF8,除非您有使用 UTF8 的特定原因。我不确定原因,但我已经看到 UTF8 编码在序列化时在某些情况下会导致这个确切的问题。

回答by Sergej Andrejev

This is BOM symbol. You can either remove it

这是 BOM 符号。你可以删除它

if (xmlString.Length > 0 && xmlString[0] != '<')
{
    xmlString = xmlString.Substring(1, xmlString.Length - 1);
}

Or use UTF32 to serialize

或者使用UTF32进行序列化

using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
{
    serializer.Serialize(writer, instance);
    result = writer.ToString();
}

And deserialize

并反序列化

object result;
using (StringReader reader = new StringReader(instance))
{
    result = serializer.Deserialize(reader);
}

If you are using this code only inside .Net applications using UTF32 won't create problems as it's the default encoding for everything inside .Net

如果您仅在使用 UTF32 的 .Net 应用程序中使用此代码不会产生问题,因为它是 .Net 中所有内容的默认编码