จัดรูปแบบสตริง XML เพื่อพิมพ์สตริง XML ที่จำง่าย


178

ฉันมีสตริง XML เป็นเช่นนี้:

<?xml version='1.0'?><response><error code='1'> Success</error></response>

ไม่มีเส้นคั่นระหว่างองค์ประกอบหนึ่งกับอีกองค์ประกอบหนึ่งและทำให้อ่านยากมาก ฉันต้องการฟังก์ชั่นที่จัดรูปแบบสตริงด้านบน:

<?xml version='1.0'?>
<response>
<error code='1'> Success</error>
</response> 

หากไม่ใช้วิธีการเขียนฟังก์ชั่นฟอร์แมตด้วยตนเองฉันจะใช้ส่วนใดของห้องสมุด. Net หรือโค้ดขนาดสั้นที่ฉันสามารถใช้แบบออฟไลน์ได้หรือไม่?


1
props ถึง CMS คำถามคือstackoverflow.com/questions/203528 ที่
Spence

2
ไม่ซ้ำกัน สิ่งนั้นระบุXmlDocumentว่าจะตัดสิทธิ์คำตอบที่โหวตสูงสุดสำหรับคำถามนี้
sirdank

คำตอบ:


185

ใช้XmlTextWriter...

public static string PrintXML(string xml)
{
    string result = "";

    MemoryStream mStream = new MemoryStream();
    XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode);
    XmlDocument document = new XmlDocument();

    try
    {
        // Load the XmlDocument with the XML.
        document.LoadXml(xml);

        writer.Formatting = Formatting.Indented;

        // Write the XML into a formatting XmlTextWriter
        document.WriteContentTo(writer);
        writer.Flush();
        mStream.Flush();

        // Have to rewind the MemoryStream in order to read
        // its contents.
        mStream.Position = 0;

        // Read MemoryStream contents into a StreamReader.
        StreamReader sReader = new StreamReader(mStream);

        // Extract the text from the StreamReader.
        string formattedXml = sReader.ReadToEnd();

        result = formattedXml;
    }
    catch (XmlException)
    {
        // Handle the exception
    }

    mStream.Close();
    writer.Close();

    return result;
}

7
วิธีนี้ใช้งานได้หากคุณกำลังจัดการกับรหัสที่อยู่ใน. NET Framework รุ่นก่อนหน้า LINQ แต่ตัวอย่างอื่น ๆ จะสะอาดกว่ามาก
Mike

8
เพื่อชี้แจงความคิดเห็นของ Mike: LINQ ถูกนำมาใช้ใน. NET 3.5 ดังนั้นหากคุณใช้. NET รุ่นเก่ากว่านั้น (. NET 1, 1.1, 2 หรือ 3.0) คุณจะต้องใช้คำตอบนี้ แต่ถ้าคุณใช้. NET 3.5 หรือใหม่กว่าคำตอบของ Charles Prakash Dasari นั้นง่ายกว่ามาก
Simon Tewsi

1
@SM Kamran ฉันใช้รหัสของคุณ แต่ฉันได้รับข้อผิดพลาดดูเหมือน {"ไม่สามารถเข้าถึงสตรีมที่ปิด"} บน writer.Close (); กรุณาให้ทางออก
Jatin Gadhiya

@JatinGadhiya ฉันมีปัญหาเดียวกันและฉันแก้ไขมันโดยใช้ {using block} ในการกำหนดสตรีม ด้วยวิธีนี้คุณไม่จำเป็นต้องปิดสตรีมด้วยตนเองและสตรีมจะถูกปิดโดยอัตโนมัติเมื่อถึงจุดสิ้นสุดของบล็อกที่ใช้
Vahid Farahmandian

312

คุณจะต้องแยกวิเคราะห์เนื้อหาอย่างใด ... ฉันพบว่าใช้ LINQ วิธีที่ง่ายที่สุดที่จะทำมัน อีกครั้งทุกอย่างขึ้นอยู่กับสถานการณ์ที่แน่นอนของคุณ นี่คือตัวอย่างการใช้งานโดยใช้ LINQ เพื่อจัดรูปแบบสตริง XML อินพุต

string FormatXml(string xml)
{
     try
     {
         XDocument doc = XDocument.Parse(xml);
         return doc.ToString();
     }
     catch (Exception)
     {
         // Handle and throw if fatal exception here; don't just ignore them
         return xml;
     }
 }

[ใช้งบเป็น ommitted เพื่อความกะทัดรัด]


สิ่งนี้จะส่งผลกระทบต่อการแบ่งบรรทัดและการเยื้องอย่างเคร่งครัดหรือไม่ ฉันไม่ต้องการการเปลี่ยนแปลงอื่น ๆ เช่น "0" ที่ถูกเปลี่ยนเป็น "0.0" ฯลฯ เมื่อช่องว่างทั้งหมดถูกถอดออกฉันต้องการให้สตริงผลลัพธ์ที่ถูกปล้นตรงกับสตริงอินพุตที่ปล้น
Radim Cernej

3
@radim ใช่ จะไม่มีการเปลี่ยนแปลงข้อมูลจริง แท็กเท่านั้นที่จะจัดรูปแบบและเยื้อง
Charles Prakash Dasari

2
ฉันสังเกตเห็นว่ามันทำงานได้ดีกับ UTF8 แต่ไม่ใช่กับไฟล์เนื้อหา Unicode XML
Nayan

1
@SteveWellens คุณสามารถเข้าถึงการประกาศผ่านทางdoc.Declaration.ToString() + doc.ToString()หรือโดยใช้แทนdoc.Save doc.ToStringดูลิงค์นี้สำหรับรายละเอียดเพิ่มเติม
David French

1
แนะนำการรวม namespaces เพื่อป้องกันผู้ใช้ไม่ต้องค้นหา namespace สำหรับคลาสที่พวกเขาอาจไม่เคยใช้มาก่อน ใช้ System.Xml.Linq; ทำงานได้ดีขอบคุณ!
Scott Moniz

61

อันนี้จาก kristopherjohnsonเป็นกองที่ดีกว่า:

  1. ไม่จำเป็นต้องมีส่วนหัวของเอกสาร XML
  2. มีข้อยกเว้นที่ชัดเจน
  3. เพิ่มตัวเลือกพฤติกรรมพิเศษ: OmitXmlDeclaration = true, NewLineOnAttributes = true
  4. บรรทัดน้อยของรหัส

    static string PrettyXml(string xml)
    {
        var stringBuilder = new StringBuilder();
    
        var element = XElement.Parse(xml);
    
        var settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.Indent = true;
        settings.NewLineOnAttributes = true;
    
        using (var xmlWriter = XmlWriter.Create(stringBuilder, settings))
        {
            element.Save(xmlWriter);
        }
    
        return stringBuilder.ToString();
    }

ทอดด์คุณช่วยอธิบายสิ่งที่คุณหมายถึงโดย "ไม่ต้องใช้ส่วนหัวของเอกสาร XML" ฉันลองใช้โซลูชันของ Charles Prakash Dasari และเพิ่งผ่านส่วน XML โดยไม่ต้องประกาศ xml (เช่นไม่มี<?xml version="1.0" encoding="UTF-8" ?>บรรทัดที่ด้านบน) และทำงานได้ดี
Simon Tewsi

3
เปรียบเทียบกับคำตอบที่ยอมรับ เมื่อเทียบกับชาร์ลส์อันนี้จะมีการกำหนดค่าที่ดีขึ้น อย่างไรก็ตามฉันอาจจะใช้วิธี Charlies ในอนาคตตัวเองความสามารถในการกำหนดค่าเช่นนี้เป็นข้อกำหนดที่หายาก
ทอดด์

1
อันนี้ดีกว่าและสั้นกว่ามาก
Alex Jolig

8

ทางออกที่ง่ายสำหรับฉัน:

        XmlDocument xmlDoc = new XmlDocument();
        StringWriter sw = new StringWriter();
        xmlDoc.LoadXml(rawStringXML);
        xmlDoc.Save(sw);
        String formattedXml = sw.ToString();

สิ่งนี้จะสร้างไฟล์ xml ด้วย <? xml version = "1.0" encoding = "utf-16"?> เป็นส่วนหัว สิ่งนี้ไม่ได้ถูกแยกวิเคราะห์โดย XmlSerializer โดยมีข้อผิดพลาด 'ไม่มีเครื่องหมายสั่งไบต์ Unicode' การแก้ไขคือการลบเข้ารหัส = "UTF-16" โปรดดูที่: stackoverflow.com/questions/29915467/...
Declan Taylor

6

ตรวจสอบลิงค์ต่อไปนี้: วิธีพิมพ์สวย XML (น่าเสียดายที่ตอนนี้ลิงก์คืนค่า 404 :()

วิธีการในการเชื่อมโยงใช้สตริง XML เป็นอาร์กิวเมนต์และส่งกลับสตริง XML ที่มีรูปแบบที่ถูกต้อง (เยื้อง)

ฉันเพิ่งคัดลอกโค้ดตัวอย่างจากลิงก์เพื่อให้คำตอบนี้ครอบคลุมและสะดวกยิ่งขึ้น

public static String PrettyPrint(String XML)
{
    String Result = "";

    MemoryStream MS = new MemoryStream();
    XmlTextWriter W = new XmlTextWriter(MS, Encoding.Unicode);
    XmlDocument D   = new XmlDocument();

    try
    {
        // Load the XmlDocument with the XML.
        D.LoadXml(XML);

        W.Formatting = Formatting.Indented;

        // Write the XML into a formatting XmlTextWriter
        D.WriteContentTo(W);
        W.Flush();
        MS.Flush();

        // Have to rewind the MemoryStream in order to read
        // its contents.
        MS.Position = 0;

        // Read MemoryStream contents into a StreamReader.
        StreamReader SR = new StreamReader(MS);

        // Extract the text from the StreamReader.
        String FormattedXML = SR.ReadToEnd();

        Result = FormattedXML;
    }
    catch (XmlException)
    {
    }

    MS.Close();
    W.Close();

    return Result;
}

2
ใช้งานได้ดีสำหรับฉันฉันเพียงแค่ทำให้มันเป็นวิธีการขยายของสตริง นอกจากนี้เว็บไซต์ดังกล่าวยังไม่ทำงานดังนั้นจึงเป็นเรื่องดีที่คุณ
ขัดขวาง

1
คำตอบซ้ำ @SM Kamran โพสต์คำตอบเดียวกันด้วย
Vahid Farahmandian

@VahidFarahmandian ใช่ ฉันทำอะไรไม่ได้มากนักเพราะฉันโพสต์เร็วกว่าเขา 1 นาที :) BTW ฉันพยายามเพิ่มว่าคำตอบนั้นมาจากที่ใดเพื่อให้เครดิตกับโปสเตอร์บล็อก น่าเสียดายที่ลิงค์เสียตอนนี้ :(.
Chansik Im

ผมชอบคำตอบนี้ที่ดีที่สุดเมื่อเทียบกับหนึ่งจากชาร์ลส์ (FormatXml) และทอดด์ (PrettyXml) เพราะคำตอบนี้ไม่ได้ตัดออก<?xml...?>เส้น คำตอบนี้ได้รับสิ่งที่ฉันมีอยู่ในใจ ข้อเสียเพียงอย่างเดียวคือฉันต้องการแท็บมากกว่าที่จะใช้ช่องว่าง ฉันตั้งค่าIndentation = 1และIndentChar = '\t'รับสิ่งที่ฉันต้องการ
Sarah Weinberger

@ CHICoder007 ขอบคุณสำหรับความคิดเห็นเกี่ยวกับวิธีการขยาย คุณสอนอะไรใหม่ ๆ ให้ฉัน การเพิ่มใน(this String XML)ผลงานที่ยอดเยี่ยม
Sarah Weinberger

4

ฉันเหนื่อย:

internal static void IndentedNewWSDLString(string filePath)
{
    var xml = File.ReadAllText(filePath);
    XDocument doc = XDocument.Parse(xml);
    File.WriteAllText(filePath, doc.ToString());
}

มันทำงานได้ดีตามที่คาดไว้


แต่สิ่งนี้จะลบแท็ก <? xml?> ที่ด้านบนสุด
Juran

2

.NET 2.0 ไม่สนใจการแก้ไขชื่อและด้วยการกำจัดทรัพยากรการเยื้องการสงวนช่องว่างและการเข้ารหัสที่เหมาะสม :

public static string Beautify(System.Xml.XmlDocument doc)
{
    string strRetValue = null;
    System.Text.Encoding enc = System.Text.Encoding.UTF8;
    // enc = new System.Text.UTF8Encoding(false);

    System.Xml.XmlWriterSettings xmlWriterSettings = new System.Xml.XmlWriterSettings();
    xmlWriterSettings.Encoding = enc;
    xmlWriterSettings.Indent = true;
    xmlWriterSettings.IndentChars = "    ";
    xmlWriterSettings.NewLineChars = "\r\n";
    xmlWriterSettings.NewLineHandling = System.Xml.NewLineHandling.Replace;
    //xmlWriterSettings.OmitXmlDeclaration = true;
    xmlWriterSettings.ConformanceLevel = System.Xml.ConformanceLevel.Document;


    using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
    {
        using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(ms, xmlWriterSettings))
        {
            doc.Save(writer);
            writer.Flush();
            ms.Flush();

            writer.Close();
        } // End Using writer

        ms.Position = 0;
        using (System.IO.StreamReader sr = new System.IO.StreamReader(ms, enc))
        {
            // Extract the text from the StreamReader.
            strRetValue = sr.ReadToEnd();

            sr.Close();
        } // End Using sr

        ms.Close();
    } // End Using ms


    /*
    System.Text.StringBuilder sb = new System.Text.StringBuilder(); // Always yields UTF-16, no matter the set encoding
    using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb, settings))
    {
        doc.Save(writer);
        writer.Close();
    } // End Using writer
    strRetValue = sb.ToString();
    sb.Length = 0;
    sb = null;
    */

    xmlWriterSettings = null;
    return strRetValue;
} // End Function Beautify

การใช้งาน:

System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("C:\Test.svg");
string SVG = Beautify(xmlDoc);

0

หากคุณโหลด XMLDoc ฉันค่อนข้างมั่นใจว่าฟังก์ชัน. ToString () มีโอเวอร์โหลดสำหรับสิ่งนี้

แต่นี่คือการดีบัก? เหตุผลที่ส่งแบบนั้นคือให้ใช้พื้นที่น้อยลง (เช่นการลบช่องว่างที่ไม่จำเป็นออกจาก XML)


0

เอาต์พุต Pretty XML ที่ปรับแต่งได้พร้อมการประกาศ UTF-8 XML

นิยามคลาสต่อไปนี้ให้วิธีการง่าย ๆ ในการแปลงสตริง XML อินพุตเป็น XML เอาต์พุตที่จัดรูปแบบด้วยการประกาศ xml เป็น UTF-8 สนับสนุนตัวเลือกการกำหนดค่าทั้งหมดที่คลาสXmlWriterSettingsเสนอ

using System;
using System.Text;
using System.Xml;
using System.IO;

namespace CJBS.Demo
{
    /// <summary>
    /// Supports formatting for XML in a format that is easily human-readable.
    /// </summary>
    public static class PrettyXmlFormatter
    {

        /// <summary>
        /// Generates formatted UTF-8 XML for the content in the <paramref name="doc"/>
        /// </summary>
        /// <param name="doc">XmlDocument for which content will be returned as a formatted string</param>
        /// <returns>Formatted (indented) XML string</returns>
        public static string GetPrettyXml(XmlDocument doc)
        {
            // Configure how XML is to be formatted
            XmlWriterSettings settings = new XmlWriterSettings 
            {
                Indent = true
                , IndentChars = "  "
                , NewLineChars = System.Environment.NewLine
                , NewLineHandling = NewLineHandling.Replace
                //,NewLineOnAttributes = true
                //,OmitXmlDeclaration = false
            };

            // Use wrapper class that supports UTF-8 encoding
            StringWriterWithEncoding sw = new StringWriterWithEncoding(Encoding.UTF8);

            // Output formatted XML to StringWriter
            using (XmlWriter writer = XmlWriter.Create(sw, settings))
            {
                doc.Save(writer);
            }

            // Get formatted text from writer
            return sw.ToString();
        }



        /// <summary>
        /// Wrapper class around <see cref="StringWriter"/> that supports encoding.
        /// Attribution: http://stackoverflow.com/a/427737/3063884
        /// </summary>
        private sealed class StringWriterWithEncoding : StringWriter
        {
            private readonly Encoding encoding;

            /// <summary>
            /// Creates a new <see cref="PrettyXmlFormatter"/> with the specified encoding
            /// </summary>
            /// <param name="encoding"></param>
            public StringWriterWithEncoding(Encoding encoding)
            {
                this.encoding = encoding;
            }

            /// <summary>
            /// Encoding to use when dealing with text
            /// </summary>
            public override Encoding Encoding
            {
                get { return encoding; }
            }
        }
    }
}

ความเป็นไปได้สำหรับการปรับปรุงเพิ่มเติม: -

  • วิธีการเพิ่มเติม GetPrettyXml(XmlDocument doc, XmlWriterSettings settings)สามารถสร้างที่อนุญาตให้ผู้เรียกปรับแต่งเอาต์พุต
  • สามารถเพิ่มวิธีการGetPrettyXml(String rawXml)เพิ่มเติมที่รองรับการแยกวิเคราะห์ข้อความดิบแทนที่จะให้ไคลเอ็นต์ใช้ XmlDocument ในกรณีของฉันฉันต้องจัดการ XML โดยใช้ XmlDocument ดังนั้นฉันจึงไม่ได้เพิ่มสิ่งนี้

การใช้งาน:

String myFormattedXml = null;
XmlDocument doc = new XmlDocument();
try
{
    doc.LoadXml(myRawXmlString);
    myFormattedXml = PrettyXmlFormatter.GetPrettyXml(doc);
}
catch(XmlException ex)
{
    // Failed to parse XML -- use original XML as formatted XML
    myFormattedXml = myRawXmlString;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.