XmlWriter để ghi vào chuỗi thay vì vào tệp


118

Tôi có một dịch vụ WCF cần trả về một chuỗi XML. Nhưng có vẻ như người viết chỉ muốn xây dựng một tập tin chứ không phải một chuỗi ký tự. Tôi đã thử:

string nextXMLstring = "";
using (XmlWriter writer = XmlWriter.Create(nextXMLstring))

Điều này tạo ra lỗi cho biết nextXMLstring không có đường dẫn tệp. Nó muốn một cái gì đó như:

using (XmlWriter writer = XmlWriter.Create("nextXMLstring.xml"))

Làm cách nào để tôi có thể xây dựng XML của mình và sau đó trả về nó dưới dạng một chuỗi ??

Cảm ơn!!

Câu trả lời:


217

Bạn cần tạo một StringWriter và chuyển nó cho XmlWriter.

Quá tải chuỗi của XmlWriter.Create là cho một tên tệp.

Ví dụ

using (var sw = new StringWriter()) {
  using (var xw = XmlWriter.Create(sw)) {
    // Build Xml with xw.


  }
  return sw.ToString();
}

2
@Will: Đã cuộn lại thay đổi của bạn. XmlTextWriter.Close () sẽ tuôn ra luồng, vì vậy muốn điều đó xảy ra trước khi giải nén chuỗi. (Little khác biệt trong trường hợp này, nhưng thích làm điều này một cách nhất quán vì ngữ nghĩa tuôn ra của * Writer và các lớp suối không phải luôn luôn ghi nhận rõ ràng.)
Richard

1
Chỉ là một nhận xét cho những người sử dụng này. Nếu bạn tình cờ bỏ qua using () và thay vào đó khai báo XmlWriter của bạn bình thường thì hãy đảm bảo gọi xw.Flush trước khi bạn gọi sw.ToString (), nếu không bạn có thể không nhận được tất cả nội dung! (Rõ ràng là tốt hơn để sử dụng các dấu ngoặc sử dụng ...)
Ravendarksky

Hãy ghi nhớ rằng đoạn mã sau cho CA2202 cảnh báo trong phân tích mã, phương pháp beacuse Dispose () sẽ được gọi là hai lần vào đối tượng StringWriter
Łukasz Kosiak

113

Như Richard đã nói, StringWriterlà con đường phía trước. Tuy nhiên, có một vấn đề: theo mặc định, StringWritersẽ tự quảng cáo là đang ở UTF-16. Thông thường, XML ở dạng UTF-8. Bạn có thể sửa lỗi này bằng cách phân lớp StringWriter;

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding
    {
         get { return Encoding.UTF8; }
    }
}

Điều này sẽ ảnh hưởng đến khai báo được viết bởi XmlWriter. Tất nhiên, nếu sau đó bạn viết chuỗi ra nơi khác ở dạng nhị phân, hãy đảm bảo rằng bạn sử dụng mã hóa phù hợp với bất kỳ mã hóa nào bạn sửa cho StringWriter. (Đoạn mã trên luôn giả định UTF-8; việc tạo một phiên bản tổng quát hơn chấp nhận một mã hóa trong hàm tạo là rất dễ dàng.)

Sau đó, bạn sẽ sử dụng:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}

Jon, bạn có chắc writerlà nó không bị vứt bỏ nhiều lần không?
rasx 21/12/10

2
@rasx: Có thể là vậy - nhưng điều đó sẽ không thành vấn đề.
Jon Skeet

30

Tôi biết điều này đã cũ và đã được giải đáp, nhưng đây là một cách khác để làm điều đó. Đặc biệt nếu bạn không muốn UTF8 BOM ở đầu chuỗi của mình và bạn muốn văn bản được thụt lề:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}

3
Encoding.UTF8.GetString(ms.ToArray())là sự đơn giản hóa trên lợi nhuận của bạn.
SliverNinja - MSFT

1
ms.ToArray()không trả lại mặt hàng nào khi tôi đã thử điều này. Phải thêm x.Close()hoặc di chuyển câu lệnh return ngay bên ngoài câu lệnh using bên trong.
Rich C

Hiện utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); công việc?
brianary

1
@Rich C - Tôi nghi ngờ điều này là do luồng của bạn không được xả. XmlTextWriter sẽ được xử lý bên ngoài câu lệnh using của nó, điều này sẽ khiến nó tuôn ra.
yourbuddypal

13

Sử dụng StringBuilder:

var sb = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(sb))
    {
        ...
    }
return sb.ToString();

1

Các bạn đừng quên gọi xmlWriter.Close () và xmlWriter.Dispose (), nếu không chuỗi của bạn sẽ không hoàn tất việc tạo. Nó sẽ chỉ là một chuỗi rỗng


Đừng lo lắng, sử dụng câu lệnh sẽ xử lý việc loại bỏ đối tượng.

Đây là một câu hỏi từ năm 2009. Vì vậy, giá trị trong việc cung cấp câu trả lời bây giờ sẽ dành cho những người dùng trong tương lai có thể gặp vấn đề tương tự. Do đó, chỉ nên cung cấp câu trả lời cho những câu hỏi cũ như thế này nếu họ có thể xác định rõ vấn đề và giải thích / đưa ra giải pháp. Thông thường sẽ không có kết quả nếu cố gắng lôi kéo OP vào một cuộc trò chuyện vì họ có thể đã tiếp tục.
MikeC

Tôi đã xem qua tất cả các ví dụ này và tự hỏi tại sao tôi nhận được chuỗi trống. xmlWriter.Close()là giải pháp.
Rafał Ryszkowski

-1

Tôi nghĩ rằng giải pháp đơn giản và nhanh nhất ở đây sẽ chỉ là:

StringBuilder sb = new StringBuilder();

using (var writer = XmlWriter.Create(sb, settings))
{
    ... // Whatever code you have/need :)

    sb = sb.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); //Or whatever uft you want/use.
    //Before you finally save it:
    File.WriteAllText("path\\dataName.xml", sb.ToString());
}
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.