Kolayca XML dizesi yazdırmak için XML dizesini biçimlendirme


178

Ben böyle bir XML dizesi var:

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

Bir öğe ile bir diğeri arasında hiç çizgi yoktur ve bu nedenle okunması çok zordur. Yukarıdaki dizeyi biçimlendiren bir işlev istiyorum:

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

Biçim işlevini kendim el ile yazmak için başvurmadan, hazırlıksız kullanabileceğim herhangi bir .Net kütüphanesi veya kod snippet'i var mı?


1
CMS'den aksesuarlar, soru yinelenen bir stackoverflow.com/questions/203528
Spence

2
Kopya değil. Bu XmlDocumentsoru, bu sorudaki en yüksek oyu alan cevabı hangisinin diskalifiye edeceğini belirtir .
sirdank

Yanıtlar:


185

Kullanın 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
Bu, LINQ öncesi .NET framework'ün eski bir sürümündeki kodla uğraşıyorsanız çalışır, ancak diğer örnek çok daha temizdir.
Mike

8
Mike'ın açıklamasını netleştirmek için: LINQ .NET 3.5'te tanıtıldı. Dolayısıyla, bundan daha eski bir .NET sürümü (.NET 1, 1.1, 2 veya 3.0) kullanıyorsanız, bu yanıtı kullanmanız gerekir. Ancak .NET 3.5 veya üstünü kullanıyorsanız Charles Prakash Dasari'nin cevabı çok daha basittir.
Simon Tewsi

1
@SM Kamran kodunuzu kullanıyorum ama hata alıyorum writer.Close () üzerinde {"Kapalı bir Akış erişilemiyor."} Gibi görünüyorum. pls çözüm verin.
Jatin Gadhiya

@JatinGadhiya Aynı sorunu yaşadım ve akışları tanımlarken {using block} kullanarak çözdüm. bu şekilde akışı manuel olarak kapatmanız gerekmez ve akışlar, kullanım bloğunun sonuna ulaşıldığında otomatik olarak kapatılır.
Vahid Farahmandian

312

İçeriği bir şekilde ayrıştırmanız gerekecek ... Bunu yapmanın en kolay yolunu LINQ kullanarak buluyorum. Yine, her şey sizin kesin senaryonuza bağlıdır. Girilen bir XML dizesini biçimlendirmek için LINQ kullanan çalışan bir örnek.

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;
     }
 }

[kısalık için ifadeler kullanılıyor]


Bu kesinlikle satır kesmelerini ve girintileri etkileyecek mi? Ben "0" "0.0" vb. Değiştiriliyor gibi başka değişiklikler istemiyorum. Tüm boşluk soyulmuş olduğunda, soyulmuş sonuç dizgisi elimden giriş dizesiyle tam olarak aynı olmasını istiyorum.
Radim Cernej

3
@radim Evet. Gerçek verilerde hiçbir değişiklik yapılmayacaktır. Yalnızca etiketler biçimlendirilir ve girintili olur.
Charles Prakash Dasari

2
UTF8 ile iyi çalıştığını fark ettim, ancak Unicode XML dosya içeriğiyle değil.
Nayan

1
@SteveWellens, bildirime bunun yerine doc.Declaration.ToString() + doc.ToString()veya aracılığıyla erişebilirsiniz . Daha fazla ayrıntı için bu bağlantıya bakın. doc.Savedoc.ToString
David French

1
Kullanıcıların daha önce hiç kullanmadığı bir sınıf için bir ad alanı aramak zorunda kalmasını engellediğinden ad alanlarını eklemeyi önerin. System.Xml.Linq kullanarak; İyi çalışıyor Teşekkürler!
Scott Moniz

61

Kristopherjohnson'dan bu daha iyi yığınlar:

  1. Bir XML belge başlığı da gerektirmez.
  2. Daha net istisnaları vardır
  3. Ek davranış seçenekleri ekler: OmitXmlDeclaration = true, NewLineOnAttributes = true
  4. Daha az kod satırı

    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();
    }

Todd, "XML belge başlığı gerektirmez" ile ne demek istediğinizi açıklayabilir misiniz? Charles Prakash Dasari'nin çözümünü denedim ve sadece xml bildirimi olmadan (yani <?xml version="1.0" encoding="UTF-8" ?>üstteki çizgi olmadan) bir XML parçasından geçtim ve iyi çalıştı.
Simon Tewsi

3
Kabul edilen cevapla karşılaştırıldığında. Charles ile karşılaştırıldığında, bu daha iyi yapılandırılabilirliğe sahip olacaktı. Ancak muhtemelen Charlies yöntemini gelecekte kendim kullanacağım, bu tür yapılandırılabilirlik nadir bir gereksinim olurdu.
Todd

1
Bu çok daha iyi ve daha kısa
Alex Jolig

8

Benim için çalışan basit çözüm:

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

bu, başlığı olarak <? xml version = "1.0" encoding = "utf-16"?> içeren bir xml dosyası oluşturur. Bu, 'Unicode bayt sırası işareti yok' hatasıyla XmlSerializer tarafından ayrıştırılmadı. Düzeltme kodlama = "utf-16" kaldırmaktı, bakınız: stackoverflow.com/questions/29915467/… .
Declan Taylor

6

Aşağıdaki bağlantıyı kontrol edin: XML nasıl güzel yazdırılır (Maalesef, bağlantı şimdi 404 döndürüyor :()

Bağlantıdaki yöntem, bir XML dizesini bağımsız değişken olarak alır ve iyi biçimlendirilmiş (girintili) bir XML dizesi döndürür.

Bu cevabı daha kapsamlı ve kullanışlı hale getirmek için bağlantıdan örnek kodu kopyaladım.

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
Benim için harika çalışıyor, ben sadece bir dize uzantısı yöntemi yaptı. Ayrıca bu web sitesi çalışmıyor, bu yüzden bir kopyasını
taktın

1
Yinelenen cevap. @SM Kamran da aynı cevabı veriyor.
Vahid Farahmandian

@VahidFarahmandian Evet. Bu konuda çok şey yapamadım çünkü ondan 1 dakika önce yayınladım :) BTW, cevabın nereden geldiğini eklemeye çalışıyordum. Ne yazık ki, bağlantı şimdi kesildi :(.
Chansik Im

Ben bu cevabı Charles (FormatXml) ve Todd (PrettyXml) ile karşılaştırıldığında en iyi, çünkü bu cevap <?xml...?>hattı çıkarmıyor . Bu cevap ilk başta aklımda olan şeyleri alıyor. Tek olumsuz yerel olarak kullanılan boşluklar yerine sekmeleri tercih ediyorum olurdu. Ben set Indentation = 1ve IndentChar = '\t'tam olarak ne istediğini alır.
Sarah Weinberger

@ CHICoder007 Uzantı yöntemi hakkındaki yorumunuz için teşekkür ederiz. Bana yeni bir şey öğrettin. (this String XML)Harika bir eser eklemek .
Sarah Weinberger

4

Denedim:

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

beklendiği gibi iyi çalışıyor.


ancak bu üstteki <? xml?> etiketini kaldırır
Juran

2

.NET 2.0, ad çözümlemeyi yok sayıyor ve uygun kaynak imhası, girintileme, koruma alanı ve özel kodlama ile :

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

Kullanımı:

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'u yüklerseniz .ToString () işlevinin bunun için bir aşırı yük içerdiğinden eminim.

Ama bu hata ayıklama için mi? Bunun gibi gönderilmesinin nedeni daha az yer kaplamaktır (yani gereksiz boşlukları XML'den çıkarmak).


0

UTF-8 XML bildirimi ile özelleştirilebilir Pretty XML çıkışı

Aşağıdaki sınıf tanımı, giriş XML dizesini xml bildirimi ile UTF-8 olarak biçimlendirilmiş çıkış XML'sine dönüştürmek için basit bir yöntem sağlar. XmlWriterSettings sınıfının sunduğu tüm yapılandırma seçeneklerini destekler .

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; }
            }
        }
    }
}

Daha da geliştirilmesi için olanaklar: -

  • GetPrettyXml(XmlDocument doc, XmlWriterSettings settings)Arayanın çıktıyı özelleştirmesine izin veren ek bir yöntem oluşturulabilir.
  • GetPrettyXml(String rawXml)İstemcinin XmlDocument'i kullanmasından ziyade ham metni ayrıştırmayı destekleyen ek bir yöntem eklenebilir. Benim durumumda, XmlDocument kullanarak XML manipüle etmek gerekiyordu, bu yüzden bunu eklemedim.

Kullanımı:

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.