2010-01-15 4 views
9

다음 코드에서 I 개체를 XML 문자열으로 serialize합니다.XDocument.Parse가이 XML 문자열을 읽도록하려면이 XML 문자열을 어떻게 변경해야합니까?

하지만 XDocument.Parse과 함께하여 XDocument으로이 XML 문자열 을 읽으려고 할 때, 그것은 나에게이 오류 제공 : 루트 수준에서

잘못된 데이터를.

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> 

UPDATE : 그것으로 읽을 수 있도록 나는이 XML에해야 할 일을

alt text http://www.deviantsart.com/upload/hhcvmu.png

: 여기은 진수입니다 오류가없는 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 + ")"; 
     } 

    } 
} 

답변 :

이 다루는 다른 사람을 위해, 여기에 BOM의 당신의 XML 청소하는 약간의 방법이다, 그래서

감사 안드라스,는 GetPreamble()는 그것을 고정 :

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; 
} 
+0

XML에 문제가 없습니다. 예외를 일으키는 XML이 동일한 것입니까? –

+0

루트 레벨 1 행 1 문자의 데이터가 잘못되었습니다. NotePad ++에 텍스트를 복사하면 첫 번째 문자는 "?"입니다. 그리고 다른 편집기에서 일부 문자 제어 ... –

+0

다음 잘라 내기 및 붙여 넣기 중에 열린 "<"를 잃었습니다. XML에는 아무런 문제가 없습니다. –

답변

15

데이터가 유니 코드 또는 utf8 BOM marks 스트림의 시작 부분에 있기 때문입니다.

스트림의 모든 바이트 주문 마크를 건너 뛸 필요가 있습니다. System.Text.Encoding.GetPreamble() 메소드에서이를 식별 할 수 있습니다.

+0

메모장에서 XML 파일을 만들 때이 문제가 자주 발생합니다. VS도 때로는 그들을 추가 할 수 있습니다. –

+0

GetPreamble() 사용은 이유 대신 결과를 해결하기위한 시도입니다. 내 대답 좀 봐. – Restuta

+0

그렇습니다. 좋은 대답입니다. 인코딩이 항상 UTF8 인 경우 작동합니다. 그러나 GetPreamble 메서드를 사용하면 파일 인코딩을 자동 검색 할 수 있습니다. 즉, 파일 인코딩 만 자동으로 감지 할 수 있습니다. 일단 선택되면 코드 샘플을 조정하여 모든 인코딩을 수용 할 수 있습니다. –

1

대신 문자열로 MemoryStream의 데이터를 변환하는 StreamReader를 사용하여 문제를 해결할 수 있습니다

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(); 
      } 
     } 
    } 
} 
+0

-1 :'XmlTextWriter'는 더 이상 사용되지 않습니다. 대신'XmlWriter.Create'를 사용하십시오. –

+0

@ 존 : 컴파일러는'XmlTextWriter'에 대한 정보를 제공하지 않습니다. 나는'XmlWriter.Create' 권고에 대해 알고 있지만 문제를 해결하는 데 필요한 것보다 OP 코드를 변경하고 싶지 않았습니다. 그래도 권장 사항을 따르기 위해 코드 샘플을 업데이트했습니다. –

-1

위의 모든 여기 정확하고 대신에 당신의 사용해야하는 코드입니다 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이 제공되지 않습니다"라고합니다. 즐겨! =)

+0

-1, -1, -1 :'MemoryStream'과'XmlWriter' 주위에'using' 블록을 넣어야합니다. .NET 2.0 이후로 더 이상 사용되지 않는'XmlTextWriter'를 사용하지 않아야합니다. 대신'XmlWriter.Create'를 사용하십시오. 'o'매개 변수는 'T'유형이어야합니다. 무엇보다도 이것은 호출자가 을 지정하지 않을 수 있습니다. 매개 변수 유형에 의해 암시되는 경우가 많습니다. –

+0

동의하지만이 코드는 수정 코드가 하나뿐이기 때문에 원본 코드를 복사 한 것이므로이를 검토하고 구멍 및 디자인 문제를 찾는 것은 내 목표가 아닙니다. 이 토론을 읽으 려한다면, 내가 묻는 문제를 해결했을 것입니다. 그러니 "-1"을 가져 가세요. – Restuta

관련 문제