Sử dụng StringWriter để tuần tự hóa XML


99

Tôi hiện đang tìm kiếm một cách dễ dàng để tuần tự hóa các đối tượng (trong C # 3).

Tôi tìm kiếm một số ví dụ và nghĩ ra một cái gì đó như:

MemoryStream memoryStream = new MemoryStream ( );
XmlSerializer xs = new XmlSerializer ( typeof ( MyObject) );
XmlTextWriter xmlTextWriter = new XmlTextWriter ( memoryStream, Encoding.UTF8 );
xs.Serialize ( xmlTextWriter, myObject);
string result = Encoding.UTF8.GetString(memoryStream .ToArray());

Sau khi đọc câu hỏi này, tôi đã tự hỏi mình, tại sao không sử dụng StringWriter? Nó có vẻ dễ dàng hơn nhiều.

XmlSerializer ser = new XmlSerializer(typeof(MyObject));
StringWriter writer = new StringWriter();
ser.Serialize(writer, myObject);
serializedValue = writer.ToString();

Một vấn đề khác là ví dụ đầu tiên tạo ra XML, tôi không thể chỉ ghi vào một cột XML của SQL Server 2005 DB.

Câu hỏi đầu tiên là: Có lý do gì tôi không nên sử dụng StringWriter để tuần tự hóa một Đối tượng khi tôi cần nó dưới dạng chuỗi sau đó không? Tôi không bao giờ tìm thấy kết quả bằng cách sử dụng StringWriter khi googling.

Tất nhiên, điều thứ hai là: Nếu bạn không nên làm điều đó với StringWriter (vì bất kỳ lý do gì), thì đó sẽ là một cách tốt và đúng?


Thêm vào:

Vì nó đã được đề cập trong cả hai câu trả lời, tôi sẽ đi sâu hơn vào vấn đề XML với DB.

Khi ghi vào Cơ sở dữ liệu, tôi có ngoại lệ sau:

System.Data.SqlClient.SqlException: Phân tích cú pháp XML: dòng 1, ký tự 38, không thể chuyển đổi mã hóa

Đối với chuỗi

<?xml version="1.0" encoding="utf-8"?><test/>

Tôi lấy chuỗi được tạo từ XmlTextWriter và chỉ cần đặt dưới dạng xml ở đó. Cái này không hoạt động (cả khi chèn thủ công vào DB).

Sau đó, tôi đã thử chèn thủ công (chỉ viết INSERT INTO ...) với encoding = "utf-16" mà cũng không thành công. Sau đó, việc xóa mã hóa hoàn toàn hoạt động. Sau kết quả đó, tôi quay lại mã StringWriter và thì đấy - nó đã hoạt động.

Vấn đề: Tôi không thực sự hiểu tại sao.

tại Christian Hayter: Với những bài kiểm tra đó, tôi không chắc rằng mình phải sử dụng utf-16 để ghi vào DB. Sau đó, đặt mã hóa thành UTF-16 (trong thẻ xml) sẽ không hoạt động?


1
Tôi đang trải nghiệm cá nhân. SQL Server chỉ chấp nhận UTF-16 và nếu bạn chuyển nó bất kỳ thứ gì khác, bạn sẽ phải chấp nhận trình phân tích cú pháp XML của SQL Server và các nỗ lực của nó để chuyển đổi dữ liệu. Thay vì cố gắng tìm cách đánh lừa nó, tôi chỉ chuyển trực tiếp UTF-16 cho nó, cách này sẽ luôn hoạt động.
Christian Hayter 14/10/09

Làm thế nào bạn đang ghi nó vào cơ sở dữ liệu? Bạn có đang chuyển nó một chuỗi hay một mảng byte hay ghi vào một luồng không? Nếu đó là một trong hai dạng sau, bạn cần đảm bảo rằng mã hóa đã khai báo khớp với mã hóa thực tế của dữ liệu nhị phân.
Jon Skeet

phew. Hướng dẫn sử dụng thử mà tôi đã thực hiện dưới dạng Truy vấn trong MS SQL Management Studio. Các lần thử "được mã hóa" được ghi vào một chuỗi mà sau đó được chuyển đến một Trình lập bản đồ O / R viết dưới dạng một chuỗi (theo chừng mực tôi có thể theo dõi). Trên thực tế, tôi đang chuyển cho nó chuỗi được tạo trong hai ví dụ được đưa ra trong câu hỏi của tôi.
StampedeXV

FYI cho người đọc - gần như trùng lặp: stackoverflow.com/questions/384974/…stackoverflow.com/questions/3760788/…
ziesemer

1
Tôi đang thay đổi câu trả lời được chấp nhận của mình vì tôi tin rằng nó thực sự trả lời câu hỏi của tôi. Mặc dù những câu trả lời khác giúp tôi tiếp tục công việc của mình, nhưng với mục đích của Stackoverflow, tôi nghĩ câu trả lời của Solomon sẽ giúp những người khác hiểu rõ hơn về những gì đã xảy ra. [Tuyên bố từ chối trách nhiệm]: Tôi không tìm thấy thời gian để thực sự xác minh câu trả lời.
StampedeXV

Câu trả lời:


1

<TL; DR> Thực ra vấn đề khá đơn giản: bạn không khớp kiểu mã hóa đã khai báo (trong khai báo XML) với kiểu dữ liệu của tham số đầu vào. Nếu bạn đã thêm vào <?xml version="1.0" encoding="utf-8"?><test/>chuỗi theo cách thủ công , thì việc khai báo SqlParameterthuộc loại SqlDbType.Xmlhoặc SqlDbType.NVarCharsẽ cho bạn lỗi "không thể chuyển đổi mã hóa". Sau đó, khi chèn theo cách thủ công qua T-SQL, vì bạn đã chuyển mã hóa đã khai báo thành utf-16, rõ ràng bạn đang chèn một VARCHARchuỗi (không có tiền tố bằng chữ hoa "N", do đó là mã hóa 8 bit, chẳng hạn như UTF-8) và không phải là mộtNVARCHAR chuỗi (có tiền tố là "N" viết hoa, do đó là mã hóa UTF-16 LE 16 bit).

Cách khắc phục phải đơn giản như sau:

  1. Trong trường hợp đầu tiên, khi thêm khai báo nêu rõ encoding="utf-8" : chỉ cần không thêm khai báo XML.
  2. Trong trường hợp thứ hai, khi thêm khai báo nêu rõ encoding="utf-16":
    1. đơn giản là không thêm khai báo XML, HOẶC
    2. chỉ cần thêm "N" vào kiểu tham số đầu vào: SqlDbType.NVarCharthay vì SqlDbType.VarChar:-) (hoặc thậm chí có thể chuyển sang sử dụng SqlDbType.Xml)

(Phản hồi chi tiết ở bên dưới)


Tất cả các câu trả lời ở đây đều quá phức tạp và không cần thiết (bất kể 121 và 184 phiếu thuận cho câu trả lời của Christian và Jon tương ứng). Họ có thể cung cấp mã làm việc, nhưng không ai trong số họ thực sự trả lời câu hỏi. Vấn đề là không ai thực sự hiểu câu hỏi, cuối cùng là về cách hoạt động của kiểu dữ liệu XML trong SQL Server. Không có gì chống lại hai người rõ ràng thông minh đó, nhưng câu hỏi này không liên quan gì đến việc tuần tự hóa sang XML. Lưu dữ liệu XML vào SQL Server dễ dàng hơn nhiều so với những gì đang được ngụ ý ở đây.

Việc tạo ra XML như thế nào không thực sự quan trọng, miễn là bạn tuân theo các quy tắc về cách tạo dữ liệu XML trong SQL Server. Tôi có giải thích kỹ lưỡng hơn (bao gồm mã ví dụ làm việc để minh họa các điểm được nêu bên dưới) trong câu trả lời cho câu hỏi này: Cách giải quyết lỗi "không thể chuyển đổi mã hóa" khi chèn XML vào SQL Server , nhưng những điều cơ bản là:

  1. Khai báo XML là tùy chọn
  2. Kiểu dữ liệu XML luôn lưu trữ các chuỗi dưới dạng UCS-2 / UTF-16 LE
  3. Nếu XML của bạn là UCS-2 / UTF-16 LE, thì bạn:
    1. chuyển vào dữ liệu dưới dạng NVARCHAR(MAX)hoặc hoặc XML/ SqlDbType.NVarChar(maxsize = -1) hoặc SqlDbType.Xml, hoặc nếu sử dụng một chuỗi ký tự thì nó phải được đặt trước bằng chữ hoa "N".
    2. nếu chỉ định khai báo XML, nó phải là "UCS-2" hoặc "UTF-16" (không có sự khác biệt thực sự ở đây)
  4. Nếu XML của bạn được mã hóa 8 bit (ví dụ: "UTF-8" / "iso-8859-1" / "Windows-1252"), thì bạn:
    1. cần chỉ định khai báo XML NẾU mã hóa khác với trang mã được chỉ định bởi Đối chiếu mặc định của cơ sở dữ liệu
    2. bạn phải chuyển vào dữ liệu dưới dạng VARCHAR(MAX)/ SqlDbType.VarChar(maxsize = -1), hoặc nếu sử dụng một chuỗi ký tự thì nó không được bắt đầu bằng chữ hoa "N".
    3. Dù sử dụng cách mã hóa 8 bit nào, thì "mã hóa" được ghi chú trong khai báo XML phải khớp với mã hóa thực tế của các byte.
    4. Mã hóa 8 bit sẽ được chuyển đổi thành UTF-16 LE bởi kiểu dữ liệu XML

Với những điểm đã nêu ở trên cho rằng các chuỗi trong .NET luôn là UTF-16 LE / UCS-2 LE (không có sự khác biệt giữa các chuỗi về mặt mã hóa), chúng tôi có thể trả lời câu hỏi của bạn:

Có lý do gì mà tôi không nên sử dụng StringWriter để tuần tự hóa một Đối tượng khi tôi cần nó dưới dạng chuỗi sau đó không?

Không, StringWritermã của bạn có vẻ ổn (ít nhất tôi không thấy có vấn đề gì trong thử nghiệm giới hạn của mình bằng cách sử dụng khối mã thứ 2 từ câu hỏi).

Sau đó, đặt mã hóa thành UTF-16 (trong thẻ xml) sẽ không hoạt động?

Không cần thiết phải cung cấp khai báo XML. Khi nó bị thiếu, mã hóa được giả định là UTF-16 LE nếu bạn chuyển chuỗi vào SQL Server dưới dạng NVARCHAR(tức là SqlDbType.NVarChar) hoặc XML(tức là SqlDbType.Xml). Mã hóa được giả định là Trang mã 8 bit mặc định nếu chuyển vào dưới dạng VARCHAR(tức là SqlDbType.VarChar). Nếu bạn có bất kỳ ký tự ASCII không chuẩn nào (tức là giá trị 128 trở lên) và đang chuyển vào dưới dạng VARCHAR, thì bạn có thể sẽ thấy "?" cho các ký tự BMP và "??" đối với Ký tự bổ sung vì SQL Server sẽ chuyển đổi chuỗi UTF-16 từ .NET thành chuỗi 8 bit của Trang mã của cơ sở dữ liệu hiện tại trước khi chuyển đổi lại thành UTF-16 / UCS-2. Nhưng bạn sẽ không nhận được bất kỳ lỗi nào.

Mặt khác, nếu bạn chỉ định khai báo XML, thì bạn phải chuyển vào SQL Server bằng cách sử dụng kiểu dữ liệu 8 bit hoặc 16 bit phù hợp. Vì vậy, nếu bạn có một khai báo cho biết mã hóa là UCS-2 hoặc UTF-16, thì bạn phải nhập bằng SqlDbType.NVarCharhoặc SqlDbType.Xml. Hoặc, nếu bạn có một tuyên bố nói rằng các mã hóa là một trong những lựa chọn 8-bit (ví dụ UTF-8, Windows-1252, iso-8859-1, vv), sau đó bạn phải vượt qua trong khi SqlDbType.VarChar. Không khớp mã hóa đã khai báo với kiểu dữ liệu SQL Server 8 hoặc 16 bit thích hợp sẽ dẫn đến lỗi "không thể chuyển đổi mã hóa" mà bạn đang gặp phải.

Ví dụ, sử dụng StringWritermã tuần tự hóa dựa trên cơ sở của bạn , tôi chỉ cần in chuỗi kết quả của XML và sử dụng nó trong SSMS. Như bạn có thể thấy bên dưới, khai báo XML được bao gồm (vì StringWriterkhông có tùy chọn OmitXmlDeclarationthích XmlWriter), điều này không có vấn đề gì miễn là bạn chuyển chuỗi vào dưới dạng kiểu dữ liệu SQL Server chính xác:

-- Upper-case "N" prefix == NVARCHAR, hence no error:
DECLARE @Xml XML = N'<?xml version="1.0" encoding="utf-16"?>
<string>Test ሴ😸</string>';
SELECT @Xml;
-- <string>Test ሴ😸</string>

Như bạn có thể thấy, nó thậm chí còn xử lý các ký tự ngoài ASCII tiêu chuẩn, với điều kiện là Điểm mã BMP U + 1234 và 😸là Điểm mã ký tự bổ sung U + 1F638. Tuy nhiên, những điều sau:

-- No upper-case "N" prefix on the string literal, hence VARCHAR:
DECLARE @Xml XML = '<?xml version="1.0" encoding="utf-16"?>
<string>Test ሴ😸</string>';

dẫn đến lỗi sau:

Msg 9402, Level 16, State 1, Line XXXXX
XML parsing: line 1, character 39, unable to switch the encoding

Ergo, tất cả lời giải thích đó sang một bên, giải pháp đầy đủ cho câu hỏi ban đầu của bạn là:

Rõ ràng bạn đã chuyển chuỗi vào dưới dạng SqlDbType.VarChar. Chuyển sang SqlDbType.NVarCharvà nó sẽ hoạt động mà không cần thực hiện thêm bước xóa khai báo XML. Điều này được ưu tiên hơn việc giữ SqlDbType.VarCharvà loại bỏ khai báo XML vì giải pháp này sẽ ngăn mất dữ liệu khi XML bao gồm các ký tự ASCII không chuẩn. Ví dụ:

-- No upper-case "N" prefix on the string literal == VARCHAR, and no XML declaration:
DECLARE @Xml2 XML = '<string>Test ሴ😸</string>';
SELECT @Xml2;
-- <string>Test ???</string>

Như bạn thấy, không có lỗi lần này, nhưng bây giờ có mất dữ liệu 🙀.


Tôi nghĩ rằng tôi là lý do cho câu trả lời phức tạp này, vì về cơ bản tôi có hai câu hỏi trong một. Tôi thực sự thích câu trả lời ngắn gọn của bạn và sẽ thử nó vào lần tới khi tôi phải lưu trữ XML trong DB. Vì vậy, nếu tôi thấy điều này đúng: bạn đã giải thích những thách thức với việc lưu trữ XML vào DB. Jon Skeet tóm tắt các vấn đề với việc sử dụng StringWriter khi làm việc với XML (ngoại trừ UTF-16) và Christian Hayter cung cấp một cách hay để làm việc với nó.
StampedeXV

@StampedeXV Tôi đã cập nhật câu trả lời của mình (một vài thay đổi để rõ ràng hơn + nội dung mới để minh họa rõ hơn các điểm). Hy vọng rằng bây giờ rõ ràng hơn rằng mặc dù cả hai câu trả lời đó đều tốt, nhưng chúng không cần thiết theo bất kỳ cách nào để trả lời câu hỏi của bạn. Họ giải quyết việc tuần tự hóa XML trong C # / .NET, nhưng câu hỏi này thực sự là về việc lưu XML trong SQL Server. Họ cung cấp thông tin hữu ích để biết và có thể là mã tốt hơn so với mã bạn đã cung cấp ban đầu, nhưng cả hai (hoặc bất kỳ thông tin nào khác ở đây), đều không thực sự đúng chủ đề. Nhưng đây không phải là thứ được ghi chép đầy đủ, do đó có sự nhầm lẫn.
Solomon Rutzky

@StampedeXV Các bản sửa đổi của tôi có hợp lý không? Tôi chỉ thêm một phần tóm tắt lên đầu có thể rõ ràng hơn. Câu chuyện ngắn: trừ khi có điều gì khác xảy ra mà bạn không đưa chi tiết vào câu hỏi, thì có vẻ như mã của bạn đúng đến 99% và có thể đã được sửa bằng cách thêm một chữ hoa duy nhất " N ”. Không cần công cụ mã hóa đặc biệt nào và mã của Christian rất hay, nhưng thử nghiệm của tôi cho thấy rằng nó trả về tuần tự hóa giống với khối mã thứ 2 của bạn, ngoại trừ việc bạn đặt CRLF sau khai báo XML. Tôi cá là bạn đã đổi thành SqlDbType.NVarCharhoặc Xml.
Solomon Rutzky

vẫn đang cố gắng tìm thời gian để tự mình kiểm tra. Nó chắc chắn nghe có vẻ hay và hợp lý, nhưng không chắc rằng điều đó sẽ đủ để thay đổi một câu trả lời được chấp nhận.
StampedeXV

216

Một vấn đề StringWriterlà theo mặc định, nó không cho phép bạn đặt mã hóa mà nó quảng cáo - vì vậy bạn có thể kết thúc với một tài liệu XML quảng cáo mã hóa của nó là UTF-16, có nghĩa là bạn cần mã hóa nó thành UTF-16 nếu bạn ghi nó vào một tập tin. Tuy nhiên, tôi có một lớp học nhỏ để giúp đỡ:

public sealed class StringWriterWithEncoding : StringWriter
{
    public override Encoding Encoding { get; }

    public StringWriterWithEncoding (Encoding encoding)
    {
        Encoding = encoding;
    }    
}

Hoặc nếu bạn chỉ cần UTF-8 (đó là tất cả những gì tôi thường cần):

public sealed class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding => Encoding.UTF8;
}

Về lý do tại sao bạn không thể lưu XML của mình vào cơ sở dữ liệu - bạn sẽ phải cung cấp cho chúng tôi thêm chi tiết về những gì đã xảy ra khi bạn thử, nếu bạn muốn chúng tôi có thể chẩn đoán / sửa chữa nó.


Tôi đã đi vào chi tiết hơn cho vấn đề cơ sở dữ liệu bây giờ. Xem câu hỏi.
StampedeXV

4
Buồn StringWriterkhông đưa vào tài khoản các mã hóa, nhưng không bao giờ ít hơn, nhờ một phương pháp ít tiện lợi :)
Châu

2
Và "Phân tích XML: dòng 1, nhân vật 38 tuổi, không có khả năng chuyển đổi các mã hóa" có thể được giải quyết bằng cách "settings.Indent = false; settings.OmitXmlDeclaration = false;"
MGE

Tôi thường giải quyết vấn đề này bằng cách đơn giản sử dụng a MemoryStreamvà a StreamWritervới mã hóa chính xác. StreamWriter một TextWriter(loại XmlWriter.Createmong đợi) với mã hóa có thể tùy chỉnh, sau tất cả.
Nyerguds

2
@Nyerguds: Vì vậy, hãy tạo một gói Nuget với những thứ như thế này, sau đó luôn dễ dàng để có được. Tôi muốn làm điều đó hơn là thỏa hiệp khả năng đọc của mã về cơ bản là về một số yêu cầu khác.
Jon Skeet

126

Khi tuần tự hóa tài liệu XML thành chuỗi .NET, mã hóa phải được đặt thành UTF-16. Các chuỗi được lưu trữ dưới dạng UTF-16 bên trong, vì vậy đây là cách mã hóa duy nhất có ý nghĩa. Nếu bạn muốn lưu trữ dữ liệu ở một bảng mã khác, bạn sử dụng một mảng byte để thay thế.

SQL Server hoạt động trên một nguyên tắc tương tự; bất kỳ chuỗi nào được chuyển vào một xmlcột phải được mã hóa dưới dạng UTF-16. SQL Server sẽ từ chối bất kỳ chuỗi nào mà khai báo XML không chỉ định UTF-16. Nếu không có khai báo XML, thì tiêu chuẩn XML yêu cầu nó mặc định là UTF-8, vì vậy SQL Server cũng sẽ từ chối điều đó.

Ghi nhớ điều này, đây là một số phương pháp tiện ích để thực hiện chuyển đổi.

public static string Serialize<T>(T value) {

    if(value == null) {
        return null;
    }

    XmlSerializer serializer = new XmlSerializer(typeof(T));

    XmlWriterSettings settings = new XmlWriterSettings()
    {
        Encoding = new UnicodeEncoding(false, false), // no BOM in a .NET string
        Indent = false,
        OmitXmlDeclaration = false
    };

    using(StringWriter textWriter = new StringWriter()) {
        using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
            serializer.Serialize(xmlWriter, value);
        }
        return textWriter.ToString();
    }
}

public static T Deserialize<T>(string xml) {

    if(string.IsNullOrEmpty(xml)) {
        return default(T);
    }

    XmlSerializer serializer = new XmlSerializer(typeof(T));

    XmlReaderSettings settings = new XmlReaderSettings();
    // No settings need modifying here

    using(StringReader textReader = new StringReader(xml)) {
        using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) {
            return (T) serializer.Deserialize(xmlReader);
        }
    }
}

Xem phần bổ sung câu hỏi. Tôi không hiểu kết quả kiểm tra của mình, nó có vẻ mâu thuẫn với tuyên bố của bạn rằng DB luôn muốn / lấy / cần UTF-16.
StampedeXV

9
Bạn không phải mã hóa dưới dạng UTF-16 - nhưng bạn phải đảm bảo rằng mã hóa bạn sử dụng phù hợp với những gì StringWritermong đợi. Hãy xem câu trả lời của tôi. Định dạng bộ nhớ trong không liên quan ở đây.
Jon Skeet 14/10/09

được rồi tôi hiểu. Trong ví dụ mới của tôi: để hoàn toàn mã hóa khiến DB tự quyết định mã hóa nào được sử dụng - đó là lý do tại sao nó hoạt động. Bây giờ tôi hiểu nó có đúng không?
StampedeXV

1
@SteveC: Xin lỗi, tôi nhầm. Tôi đã chuyển đổi thủ công mã từ VB, mã Nothingnày hoàn toàn có thể chuyển đổi thành bất kỳ loại nào. Tôi đã sửa Deserializemã. Các Serializecảnh báo phải là một điều Resharper chỉ, trình biên dịch tự nó không phản đối và nó là hợp pháp để làm.
Christian Hayter

1
Mở rộng theo bình luận của Jon Skeet, không, UTF-16 không bắt buộc. Vui lòng tham khảo stackoverflow.com/a/8998183/751158 để biết ví dụ cụ thể chứng minh điều này.
ziesemer

20

Trước hết, hãy cẩn thận khi tìm các ví dụ cũ. Bạn đã tìm thấy một cái sử dụng XmlTextWriter, không được dùng nữa kể từ .NET 2.0. XmlWriter.Createnên được sử dụng thay thế.

Dưới đây là một ví dụ về việc tuần tự hóa một đối tượng thành một cột XML:

public void SerializeToXmlColumn(object obj)
{
    using (var outputStream = new MemoryStream())
    {
        using (var writer = XmlWriter.Create(outputStream))
        {
            var serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);
        }

        outputStream.Position = 0;
        using (var conn = new SqlConnection(Settings.Default.ConnectionString))
        {
            conn.Open();

            const string INSERT_COMMAND = @"INSERT INTO XmlStore (Data) VALUES (@Data)";
            using (var cmd = new SqlCommand(INSERT_COMMAND, conn))
            {
                using (var reader = XmlReader.Create(outputStream))
                {
                    var xml = new SqlXml(reader);

                    cmd.Parameters.Clear();
                    cmd.Parameters.AddWithValue("@Data", xml);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}

2
Tôi chỉ có thể bình chọn điều này một lần, nhưng đây xứng đáng là câu trả lời hàng đầu ở đây. Cuối cùng, không quan trọng mã hóa được khai báo hoặc sử dụng, miễn là XmlReadercó thể phân tích cú pháp nó. Nó sẽ được gửi trước khi phân tích cú pháp đến cơ sở dữ liệu và sau đó DB không cần biết bất kỳ điều gì về mã hóa ký tự - UTF-16 hoặc cách khác. Đặc biệt, hãy lưu ý rằng các khai báo XML thậm chí không tồn tại với dữ liệu trong cơ sở dữ liệu, bất kể phương pháp nào được sử dụng để chèn nó. Vui lòng không lãng phí bằng cách chạy XML thông qua các chuyển đổi bổ sung, như được hiển thị trong các câu trả lời khác ở đây và nơi khác.
ziesemer

1
public static T DeserializeFromXml<T>(string xml)
{
    T result;
    XmlSerializerFactory serializerFactory = new XmlSerializerFactory();
    XmlSerializer serializer =serializerFactory.CreateSerializer(typeof(T));

    using (StringReader sr3 = new StringReader(xml))
    {
        XmlReaderSettings settings = new XmlReaderSettings()
        {
            CheckCharacters = false // default value is true;
        };

        using (XmlReader xr3 = XmlTextReader.Create(sr3, settings))
        {
            result = (T)serializer.Deserialize(xr3);
        }
    }

    return result;
}

-1

Nó có thể đã được đề cập ở những nơi khác nhưng chỉ cần thay đổi dòng mã hóa của nguồn XML thành 'utf-16' sẽ cho phép chèn XML vào kiểu xml'data của SQL Server.

using (DataSetTableAdapters.SQSTableAdapter tbl_SQS = new DataSetTableAdapters.SQSTableAdapter())
{
    try
    {
        bodyXML = @"<?xml version="1.0" encoding="UTF-8" standalone="yes"?><test></test>";
        bodyXMLutf16 = bodyXML.Replace("UTF-8", "UTF-16");
        tbl_SQS.Insert(messageID, receiptHandle, md5OfBody, bodyXMLutf16, sourceType);
    }
    catch (System.Data.SqlClient.SqlException ex)
    {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
    }
}

Kết quả là tất cả văn bản XML được chèn vào trường kiểu dữ liệu 'xml' nhưng dòng 'tiêu đề' bị xóa. Những gì bạn thấy trong bản ghi kết quả chỉ là

<test></test>

Sử dụng phương pháp tuần tự hóa được mô tả trong mục nhập "Đã trả lời" là một cách để đưa tiêu đề gốc vào trường đích nhưng kết quả là văn bản XML còn lại được bao bọc trong một XML <string></string> thẻ .

Bộ điều hợp bảng trong mã là một lớp được tạo tự động bằng cách sử dụng Visual Studio 2013 "Add New Data Source: wizard. Năm tham số cho phương thức Chèn ánh xạ tới các trường trong bảng SQL Server.


2
Thay thế? Điều này thật vui nhộn.
mgilberties

2
Nghiêm túc - đừng làm điều này. Không bao giờ. Điều gì sẽ xảy ra nếu tôi muốn đưa một số đoạn văn xuôi vào xml của mình có đề cập đến "UTF-8" - bạn vừa thay đổi dữ liệu của tôi thành điều gì đó mà tôi không nói!
Tim Abell,

2
Cảm ơn vì đã chỉ ra một sai sót trong mã. Thay vì bodyXML.Replace ("UTF-8", "UTF-16"), phải có mã tập trung vào tiêu đề XML thay đổi UTF-8 thành UTF-16. Điều tôi thực sự đang cố gắng chỉ ra là bằng cách thực hiện thay đổi này trong tiêu đề của nguồn XML, sau đó phần thân của XML sau đó có thể được chèn vào bản ghi bảng SQL bằng cách sử dụng trường kiểu dữ liệu XML và tiêu đề bị loại bỏ. Vì lý do bây giờ tôi không nhớ (bốn năm trước!), Kết quả là một thứ hữu ích vào thời điểm đó. Và có, sai lầm ngớ ngẩn khi sử dụng 'Replace'. Nó xảy ra.
DLG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.