XmlDocument से लाइन ब्रेक के साथ इंडेंटेड XML प्राप्त करने का सबसे सरल तरीका क्या है?


105

जब मैं XML को स्क्रैच से तैयार करता हूं XmlDocument, तो OuterXmlसंपत्ति में पहले से ही लाइन ब्रेक के साथ सब कुछ ठीक है। हालांकि, अगर मैं LoadXmlकुछ बहुत ही "संकुचित" एक्सएमएल पर कॉल करता हूं (कोई लाइन नहीं टूटती है या किसी का ध्यान नहीं जाता है) तो आउटपुट OuterXmlउस तरह से रहता है। इसलिए ...

किसके उदाहरण से सुशोभित XML आउटपुट प्राप्त करने का सबसे सरल तरीका है XmlDocument?

जवाबों:


209

अन्य उत्तरों के आधार पर, मैंने देखा XmlTextWriterऔर निम्नलिखित सहायक विधि के साथ आया:

static public string Beautify(this XmlDocument doc)
{
    StringBuilder sb = new StringBuilder();
    XmlWriterSettings settings = new XmlWriterSettings
    {
        Indent = true,
        IndentChars = "  ",
        NewLineChars = "\r\n",
        NewLineHandling = NewLineHandling.Replace
    };
    using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
        doc.Save(writer);
    }
    return sb.ToString();
}

यह मेरे लिए उम्मीद से थोड़ा अधिक कोड है, लेकिन यह सिर्फ आड़ू का काम करता है।


5
तुम भी XmlDocument वर्ग के लिए एक विस्तार विधि के रूप में अपनी उपयोगिता विधि बनाने पर विचार कर सकते हैं।
विपक्षी दल

5
अजीब तरह से, मेरे लिए यह UTF-16 में xml हैडर की एन्कोडिंग सेट करने के अलावा कुछ भी नहीं है। बहुत अजीब बात है, यह तब भी होता है जब मैं स्पष्ट रूप से सेट करता हूंsettings.Encoding = Encoding.UTF8;
Nyerguds

3
एन्कोडिंग समस्या को इसके बजाय निर्दिष्ट एन्कोडिंग के साथ MemoryStream+ का उपयोग करके और पाठ के साथ प्राप्त करके हल किया जा सकता है । अंतिम परिणाम अभी भी किसी भी तरह से स्वरूपित नहीं है, हालांकि। क्या यह संबंधित हो सकता है कि मैं पढ़े गए दस्तावेज़ से शुरू कर रहा हूं जिसमें पहले से ही प्रारूपण है? मैं बस चाहता हूं कि मेरे नए नोड्स को भी स्वरूपित किया जाए। StreamWriterStringBuilderenc.GetString(memstream.GetBuffer(), 0, (int)memstream.Length);
Nyerguds

2
मैं करने के "\r\n"लिए संशोधित करने के लिए परीक्षा दे रहा हूँ Environment.Newline
छत्र

2
doc.PreserveWhitespaceसत्य पर सेट नहीं होना चाहिए। अन्यथा यह विफल हो जाता है अगर इसमें पहले से ही आंशिक इंडेंटेशन हो।
मास्टर डीजेन

48

इरिका एर्ली के ब्लॉग से अनुकूलित के रूप में , यह करना चाहिए:

XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>");
// Save the document to a file and auto-indent the output.
using (XmlTextWriter writer = new XmlTextWriter("data.xml", null)) {
    writer.Formatting = Formatting.Indented;
    doc.Save(writer);
}

10
usingबयान का समापन स्वचालित रूप से लेखक को बंद कर दिया जाएगा जब Dispose()कहा जाता है।
टायलर ली

3
मेरे लिए, यह केवल एक लाइन का संकेत देता है। मेरे पास अभी भी दर्जनों अन्य लाइनें हैं जो इंडेंट नहीं हैं।
सी जॉनसन

40

या और भी आसान है अगर आपके पास Linq की पहुँच है

try
{
    RequestPane.Text = System.Xml.Linq.XElement.Parse(RequestPane.Text).ToString();
}
catch (System.Xml.XmlException xex)
{
            displayException("Problem with formating text in Request Pane: ", xex);
}

बहुत अच्छा! ऊपर अंगूठे स्वीकार किए जाते हैं जवाब से अधिक लाभ यह है कि यह एक XML टिप्पणी का उत्पादन नहीं होगा तो एक XML टुकड़ा के लिए बेहतर काम करता है
उमर फारूक ख्वाजा

3
अजीब तरह से, यह <?xml ...?>और <!DOCTYPE ...>XML से हटा देता है । एक टुकड़े के लिए ठीक है, लेकिन एक पूर्ण दस्तावेज़ के लिए वांछनीय नहीं है।
जेसी चिशोल्म

यह एकमात्र तरीका है जिसने मेरे लिए काम किया। Xmltextwriter, Formatting = Formatting.Indented और XmlWriterSettings का उपयोग करते हुए अन्य सभी विधियाँ पाठ में सुधार नहीं करती हैं, लेकिन यह विधि करती है।
kexx

16

एक छोटा विस्तार विधि संस्करण

public static string ToIndentedString( this XmlDocument doc )
{
    var stringWriter = new StringWriter(new StringBuilder());
    var xmlTextWriter = new XmlTextWriter(stringWriter) {Formatting = Formatting.Indented};
    doc.Save( xmlTextWriter );
    return stringWriter.ToString();
}

यह बहुत अच्छी तरह से काम करता है और डिस्क में अनावश्यक फ़ाइलों को बनाना शामिल नहीं है
ज़ैन रिज़वी

13

यदि उपरोक्त सुशोभित विधि को XmlDocumentउस के लिए बुलाया जा रहा है जिसमें पहले से ही एक XmlProcessingInstructionबच्चा नोड है तो निम्नलिखित अपवाद फेंका गया है:

XML घोषणा नहीं लिख सकते। WriteStartDocument विधि ने इसे पहले ही लिखा है।

यह अपवाद से छुटकारा पाने के लिए मूल एक का मेरा संशोधित संस्करण है:

private static string beautify(
    XmlDocument doc)
{
    var sb = new StringBuilder();
    var settings =
        new XmlWriterSettings
            {
                Indent = true,
                IndentChars = @"    ",
                NewLineChars = Environment.NewLine,
                NewLineHandling = NewLineHandling.Replace,
            };

    using (var writer = XmlWriter.Create(sb, settings))
    {
        if (doc.ChildNodes[0] is XmlProcessingInstruction)
        {
            doc.RemoveChild(doc.ChildNodes[0]);
        }

        doc.Save(writer);
        return sb.ToString();
    }
}

यह अब मेरे लिए काम करता है, शायद आपको नोड के लिए सभी बच्चे नोड्स को स्कैन करने की आवश्यकता होगी XmlProcessingInstruction, न कि पहले एक ही?


अप्रैल 2015 को अपडेट करें:

चूँकि मेरे पास एक और मामला था जहाँ एन्कोडिंग गलत थी, इसलिए मैंने बिना बॉम के UTF-8 को लागू करने का तरीका खोजा। मुझे यह ब्लॉग पोस्ट मिला और इस पर आधारित एक समारोह बनाया:

private static string beautify(string xml)
{
    var doc = new XmlDocument();
    doc.LoadXml(xml);

    var settings = new XmlWriterSettings
    {
        Indent = true,
        IndentChars = "\t",
        NewLineChars = Environment.NewLine,
        NewLineHandling = NewLineHandling.Replace,
        Encoding = new UTF8Encoding(false)
    };

    using (var ms = new MemoryStream())
    using (var writer = XmlWriter.Create(ms, settings))
    {
        doc.Save(writer);
        var xmlString = Encoding.UTF8.GetString(ms.ToArray());
        return xmlString;
    }
}

यदि आप माता-पिता के नोड के अंदर और बच्चे के नोड से पहले cdata अनुभाग डालते हैं तो यह काम नहीं करेगा
साशा बॉन्ड

2
मैमोरीस्ट्रीम की जरूरत नहीं लगती, कम से कम मेरी तरफ। मैंने जो सेटिंग की है Encoding = Encoding.UTF8OmitXmlDeclaration = true
उसमें


5
    public static string FormatXml(string xml)
    {
        try
        {
            var doc = XDocument.Parse(xml);
            return doc.ToString();
        }
        catch (Exception)
        {
            return xml;
        }
    }

नीचे दिए गए उत्तर निश्चित रूप से कुछ स्पष्टीकरण के साथ कर सकते हैं लेकिन यह मेरे लिए काम करता है और अन्य समाधानों की तुलना में बहुत सरल है।
कार्ल

ऐसा लगता है कि आपको PS 3 पर काम करने के लिए system.link.XML असेंबली को आयात करने की आवश्यकता है।
कार्लर

2

उपयोग करने का एक सरल तरीका है:

writer.WriteRaw(space_char);

नमूना कोड की तरह, यह कोड वह है जो मैंने XMLWriter का उपयोग करके संरचना की तरह एक ट्री व्यू बनाने के लिए किया था:

private void generateXML(string filename)
        {
            using (XmlWriter writer = XmlWriter.Create(filename))
            {
                writer.WriteStartDocument();
                //new line
                writer.WriteRaw("\n");
                writer.WriteStartElement("treeitems");
                //new line
                writer.WriteRaw("\n");
                foreach (RootItem root in roots)
                {
                    //indent
                    writer.WriteRaw("\t");
                    writer.WriteStartElement("treeitem");
                    writer.WriteAttributeString("name", root.name);
                    writer.WriteAttributeString("uri", root.uri);
                    writer.WriteAttributeString("fontsize", root.fontsize);
                    writer.WriteAttributeString("icon", root.icon);
                    if (root.children.Count != 0)
                    {
                        foreach (ChildItem child in children)
                        {
                            //indent
                            writer.WriteRaw("\t");
                            writer.WriteStartElement("treeitem");
                            writer.WriteAttributeString("name", child.name);
                            writer.WriteAttributeString("uri", child.uri);
                            writer.WriteAttributeString("fontsize", child.fontsize);
                            writer.WriteAttributeString("icon", child.icon);
                            writer.WriteEndElement();
                            //new line
                            writer.WriteRaw("\n");
                        }
                    }
                    writer.WriteEndElement();
                    //new line
                    writer.WriteRaw("\n");
                }

                writer.WriteEndElement();
                writer.WriteEndDocument();

            }

        }

इस तरह से आप टैब या लाइन ब्रेक को उस तरह से जोड़ सकते हैं जिस तरह से आप सामान्य रूप से उपयोग करते हैं, यानी \ t या \ n


1

यहां पोस्ट किए गए सुझावों को लागू करते समय, मुझे टेक्स्ट एन्कोडिंग से परेशानी हुई। ऐसा लगता है कि एन्कोडिंग XmlWriterSettingsको अनदेखा किया गया है, और हमेशा स्ट्रीम के एन्कोडिंग द्वारा ओवरराइड किया जाता है। ए का उपयोग करते समय StringBuilder, यह हमेशा सी #, अर्थात् यूटीएफ -16 में आंतरिक रूप से उपयोग किए जाने वाले पाठ एन्कोडिंग है।

तो यहाँ एक संस्करण है जो अन्य एन्कोडिंग का भी समर्थन करता है।

महत्वपूर्ण नोट: यदि दस्तावेज़ को लोड करते समय आपकी XMLDocumentवस्तु preserveWhitespaceसक्षम है, तो स्वरूपण को पूरी तरह से अनदेखा कर दिया जाता है । इसने मुझे कुछ समय के लिए रोक दिया था, इसलिए सुनिश्चित करें कि इसे सक्षम न करें।

मेरा अंतिम कोड:

public static void SaveFormattedXml(XmlDocument doc, String outputPath, Encoding encoding)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.IndentChars = "\t";
    settings.NewLineChars = "\r\n";
    settings.NewLineHandling = NewLineHandling.Replace;

    using (MemoryStream memstream = new MemoryStream())
    using (StreamWriter sr = new StreamWriter(memstream, encoding))
    using (XmlWriter writer = XmlWriter.Create(sr, settings))
    using (FileStream fileWriter = new FileStream(outputPath, FileMode.Create))
    {
        if (doc.ChildNodes.Count > 0 && doc.ChildNodes[0] is XmlProcessingInstruction)
            doc.RemoveChild(doc.ChildNodes[0]);
        // save xml to XmlWriter made on encoding-specified text writer
        doc.Save(writer);
        // Flush the streams (not sure if this is really needed for pure mem operations)
        writer.Flush();
        // Write the underlying stream of the XmlWriter to file.
        fileWriter.Write(memstream.GetBuffer(), 0, (Int32)memstream.Length);
    }
}

यह दिए गए पाठ एन्कोडिंग के साथ स्वरूपित xml को डिस्क में सहेज देगा।


1

यदि आपके पास उपयोग के लिए तैयार डॉक के बजाय XML का एक स्ट्रिंग है, तो आप इसे इस तरह से कर सकते हैं:

var xmlString = "<xml>...</xml>"; // Your original XML string that needs indenting.
xmlString = this.PrettifyXml(xmlString);

private string PrettifyXml(string xmlString)
{
    var prettyXmlString = new StringBuilder();

    var xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmlString);

    var xmlSettings = new XmlWriterSettings()
    {
        Indent = true,
        IndentChars = " ",
        NewLineChars = "\r\n",
        NewLineHandling = NewLineHandling.Replace
    };

    using (XmlWriter writer = XmlWriter.Create(prettyXmlString, xmlSettings))
    {
        xmlDoc.Save(writer);
    }

    return prettyXmlString.ToString();
}

1

स्वीकृत उत्तर के आधार पर अधिक सरलीकृत दृष्टिकोण:

static public string Beautify(this XmlDocument doc) {
    StringBuilder sb = new StringBuilder();
    XmlWriterSettings settings = new XmlWriterSettings
    {
        Indent = true
    };

    using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
        doc.Save(writer);
    }

    return sb.ToString(); 
}

नई लाइन सेट करना आवश्यक नहीं है। इंडेंट कैरेक्टर्स में डिफॉल्ट दो स्पेस भी होते हैं इसलिए मैंने इसे सेट नहीं करना पसंद किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.