代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

如何更改此XML字符串,以便xdocument.parse读取它?

  •  10
  • Edward Tanguay  · 技术社区  · 15 年前

    在下面的代码中,我 串行化 对象转换为XML 一串 .

    但是当我试图读取这个XML字符串时 变成一个文件 对于xdocument.parse,它给了我这个 错误 :

    根级别的数据无效。

    XML是:

    <?xml version="1.0" encoding="utf-8"?>
    <Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <Id>1</Id>
       <FirstName>Jim</FirstName>
       <LastName>Jones</LastName>
       <ZipCode>23434</ZipCode>
    </Customer>
    

    更新: 这是十六进制:

    ![alt text][1] mod edit-禁用的超链接:指向恶意软件的链接

    我必须对这个XML做些什么,以便它能够在不出错的情况下读取到XDocument中?

    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;
    using System.IO;
    using System.Xml;
    using System.Text;
    using System.Xml.Linq;
    
    namespace TestSerialize2342
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<Customer> customers = Customer.GetCustomers();
    
                Console.WriteLine("--- Serializing ------------------");
    
                foreach (var customer in customers)
                {
                    Console.WriteLine("Serializing " + customer.GetFullName() + "...");
                    string xml = XmlHelpers.SerializeObject<Customer>(customer);
    
                    XDocument xdoc = XDocument.Parse(xml);
    
                }
    
                Console.ReadLine();
            }
    
        }
    
        public static class StringHelpers
        {
            public static String UTF8ByteArrayToString(Byte[] characters)
            {
                UTF8Encoding encoding = new UTF8Encoding();
                String constructedString = encoding.GetString(characters);
                return (constructedString);
            }
    
            public static Byte[] StringToUTF8ByteArray(String pXmlString)
            {
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] byteArray = encoding.GetBytes(pXmlString);
                return byteArray;
            } 
        }
    
        public static class XmlHelpers
        {
            public static string SerializeObject<T>(object o)
            {
                MemoryStream ms = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(typeof(T));
                XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
                xs.Serialize(xtw, o);
                ms = (MemoryStream)xtw.BaseStream;
                return StringHelpers.UTF8ByteArrayToString(ms.ToArray());
            }
    
            public static T DeserializeObject<T>(string xml)
            {
                XmlSerializer xs = new XmlSerializer(typeof(T));
                MemoryStream ms = new MemoryStream(StringHelpers.StringToUTF8ByteArray(xml));
                XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
                return (T)xs.Deserialize(ms);
            }
        }
    
        public class Customer
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Street { get; set; }
            public string Location { get; set; }
            public string ZipCode { get; set; }
    
            private int internalValue = 23;
    
            public static List<Customer> GetCustomers()
            {
                List<Customer> customers = new List<Customer>();
                customers.Add(new Customer { Id = 1, FirstName = "Jim", LastName = "Jones", ZipCode = "23434" });
                customers.Add(new Customer { Id = 2, FirstName = "Joe", LastName = "Adams", ZipCode = "12312" });
                customers.Add(new Customer { Id = 3, FirstName = "Jack", LastName = "Johnson", ZipCode = "23111" });
                customers.Add(new Customer { Id = 4, FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" });
                customers.Add(new Customer { Id = 5, FirstName = "Henry", LastName = "Anderson", ZipCode = "16623" });
                return customers;
            }
    
            public string GetFullName()
            {
                return FirstName + " " + LastName + "(" + internalValue + ")";
            }
    
        }
    }
    

    答:

    感谢Andras,getPreamble()修复了它,因此对于其他处理此问题的人,这里有一个清理BOM XML的小方法:

    public static string RemoveUtf8ByteOrderMark(string xml)
    {
        string byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
        if (xml.StartsWith(byteOrderMarkUtf8))
        {
            xml = xml.Remove(0, byteOrderMarkUtf8.Length);
        }
        return xml;
    }
    
    3 回复  |  直到 7 年前
        1
  •  15
  •   Andras Zoltan    15 年前

    因为数据包含unicode或utf8 BOM marks 在溪流的起点。

    您需要跳过流中的任何字节顺序标记-您可以从 System.Text.Encoding.GetPreamble() 方法。

        2
  •  1
  •   Fredrik Mörk    15 年前

    您可以使用 StreamReader 转换中的数据 MemoryStream 改为字符串:

    public static string SerializeObject<T>(object o)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            using (XmlWriter xtw = XmlWriter.Create(ms))
            {
                xs.Serialize(xtw, o);
                xtw.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                using (StreamReader reader = new StreamReader(ms))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
    
        3
  •  -1
  •   Restuta    15 年前

    以上都是正确的,下面是一个代码,您应该使用它来跳过BOM:

     public static string SerializeObject<T>(object o)
            {
                MemoryStream ms = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(typeof(T));
                //here is my code
                UTF8Encoding encoding = new UTF8Encoding(false);
                XmlTextWriter xtw = new XmlTextWriter(ms, encoding);
                //XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
                xs.Serialize(xtw, o);
                ms = (MemoryStream)xtw.BaseStream;
                return StringHelpers.UTF8ByteArrayToString(ms.ToArray());
           }
    

    通过指定 在构造函数中,您会说“没有提供BOM”。享受!=)