XmlWriter เพื่อเขียนลงในสตริงแทนที่จะเป็นไฟล์


118

ฉันมีบริการ WCF ที่ต้องการส่งคืนสตริง XML แต่ดูเหมือนว่าผู้เขียนต้องการสร้างไฟล์เท่านั้นไม่ใช่สตริง ฉันเหนื่อย:

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

สิ่งนี้สร้างข้อผิดพลาดว่า nextXMLstring ไม่มีเส้นทางไฟล์ มันต้องการสิ่งที่ชอบ:

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

ฉันจะสร้าง XML ของฉันแล้วส่งคืนเป็นสตริงได้อย่างไร?

ขอบคุณ !!

คำตอบ:


217

คุณต้องสร้าง StringWriter และส่งต่อไปยัง XmlWriter

การโอเวอร์โหลดสตริงของ XmlWriter.Create สำหรับชื่อไฟล์

เช่น

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


  }
  return sw.ToString();
}

2
@ Will: รีดคืนการเปลี่ยนแปลงของคุณ XmlTextWriter.Close () จะล้างไปยังสตรีมดังนั้นต้องการให้สิ่งนั้นเกิดขึ้นก่อนที่จะแยกสตริง (ความแตกต่างเพียงเล็กน้อยในกรณีนี้ แต่ชอบที่จะทำสิ่งนี้อย่างสม่ำเสมอเนื่องจากความหมายที่ชัดเจนของคลาส * Writer และ Stream ไม่ได้รับการบันทึกไว้อย่างชัดเจนเสมอไป)
Richard

1
แค่ความคิดเห็นสำหรับคนที่ใช้สิ่งนี้ หากคุณบังเอิญละเว้นการใช้ () และประกาศ XmlWriter ของคุณตามปกติแทนที่จะเรียกใช้ xw.Flush ก่อนที่คุณจะเรียกใช้ sw ToString () มิฉะนั้นคุณอาจไม่ได้รับเนื้อหาทั้งหมด! (เห็นได้ชัดว่าดีกว่าที่จะใช้วงเล็บโดยใช้ ... )
Ravendarksky

โปรดทราบว่ารหัสต่อไปนี้ให้คำเตือน CA2202 ในระหว่างการวิเคราะห์โค้ดวิธี beacuse Dispose () จะถูกเรียกสองครั้งบนวัตถุ StringWriter
Łukasz Kosiak

113

ดังที่ริชาร์ดกล่าวStringWriterคือหนทางข้างหน้า อย่างไรก็ตามมีอุปสรรคอย่างหนึ่ง: โดยค่าเริ่มต้นStringWriterจะโฆษณาตัวเองว่าอยู่ใน UTF-16 โดยปกติ XML จะอยู่ใน UTF-8 คุณสามารถแก้ไขได้โดยคลาสย่อย StringWriter;

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

XmlWriterซึ่งจะส่งผลกระทบต่อการประกาศที่เขียนโดย แน่นอนว่าถ้าคุณเขียนสตริงออกไปที่อื่นในรูปแบบไบนารีตรวจสอบให้แน่ใจว่าคุณใช้การเข้ารหัสที่ตรงกับการเข้ารหัสใดก็ตามที่คุณแก้ไขสำหรับStringWriter. (รหัสด้านบนถือว่า UTF-8 เสมอมันเป็นเรื่องเล็กน้อยที่จะสร้างเวอร์ชันทั่วไปที่ยอมรับการเข้ารหัสในตัวสร้าง)

จากนั้นคุณจะใช้:

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

จอนแน่ใจหรือว่าwriterไม่ถูกกำจัดมากกว่าหนึ่งครั้ง?
rasx

2
@rasx: มันอาจจะเป็น - แต่มันจะไม่สำคัญ
Jon Skeet

30

ฉันรู้ว่านี่เป็นเรื่องเก่าและตอบได้ แต่นี่เป็นอีกวิธีหนึ่งที่จะทำได้ โดยเฉพาะอย่างยิ่งถ้าคุณไม่ต้องการให้ UTF8 BOM ที่จุดเริ่มต้นของสตริงของคุณและคุณต้องการให้ข้อความเยื้อง:

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())เป็นการลดความซับซ้อนในการกลับมาของคุณ
SliverNinja - MSFT

1
ms.ToArray()ไม่ส่งคืนรายการเมื่อฉันลองสิ่งนี้ ต้องเพิ่มx.Close()หรือย้ายคำสั่ง return ด้านนอกของ inner using statement
Rich C

utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); งาน?
brianary

1
@ Rich C - ฉันสงสัยว่านี่เป็นเพราะสตรีมของคุณไม่ถูกล้าง XmlTextWriter จะถูกกำจัดออกไปนอกคำสั่งการใช้งานซึ่งจะทำให้ล้างออก
yourbuddypal

15

ใช้StringBuilder:

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

1

อย่าลืมเรียก xmlWriter.Close () และ xmlWriter.Dispose () มิฉะนั้นสตริงของคุณจะสร้างไม่เสร็จ มันจะเป็นสตริงว่างเปล่า


ไม่ต้องกังวลการใช้คำสั่งจะจัดการกับการทิ้งวัตถุ

นี่เป็นคำถามจากปี 2009 ดังนั้นมูลค่าในการให้คำตอบในตอนนี้คือสำหรับผู้ใช้ในอนาคตที่อาจมีปัญหาคล้ายกัน ดังนั้นควรให้คำตอบสำหรับคำถามเก่า ๆ เช่นนี้ก็ต่อเมื่อพวกเขาสามารถระบุปัญหาได้อย่างชัดเจนและอธิบาย / ให้แนวทางแก้ไข โดยปกติแล้วการพยายามมีส่วนร่วมกับ OP ในการสนทนาเป็นเรื่องที่ไร้ผลเนื่องจากพวกเขามีแนวโน้มที่จะดำเนินต่อไป
MikeC

ฉันกำลังดูตัวอย่างทั้งหมดนี้และสงสัยว่าทำไมฉันถึงได้สตริงว่างเปล่า xmlWriter.Close()เป็นทางออก
Rafał Ryszkowski

-1

ฉันคิดว่าวิธีแก้ปัญหาที่ง่ายและเร็วที่สุดคือ:

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());
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.