わかりやすいXML文字列を出力するためのXML文字列のフォーマット


178

そのようなXML文字列があります:

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

1つの要素と別の要素の間に線がないため、非常に読みにくくなっています。上記の文字列をフォーマットする関数が必要です。

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

自分でフォーマット関数を手動で作成する必要がない場合、オフハンドで使用できる.Netライブラリまたはコードスニペットはありますか?


1
CMSの小道具、質問は重複しています。stackoverflow.com
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フレームワークのLINQより前のコードを処理している場合に機能しますが、他の例はよりクリーンです。
Mike

8
Mikeのコメントを明確にするために:LINQは.NET 3.5で導入されました。したがって、それより古いバージョンの.NET(.NET 1、1.1、2、または3.0)を使用している場合は、この回答を使用する必要があります。ただし、.NET 3.5以降を使用している場合は、Charles Prakash Dasariの方がはるかに簡単です。
Simon Tewsi 2013

1
@SMカムランコードを使用していますが、writer.Close();で{"Cannot access to a closed stream。"}のようなエラーが表示されます。plsは解決策を与えます。
Jatin Gadhiya、2014

@JatinGadhiya同じ問題が発生したため、ストリームの定義に{using block}を使用して解決しました。この方法では、ストリームを手動で閉じる必要はなく、usingブロックの最後に到達すると、ストリームは自動的に閉じられます。
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;
     }
 }

[簡潔にするため、ステートメントの使用は省略しています]


これは改行とインデントに厳密に影響しますか?「0」が「0.0」に変更されるなど、他の変更はしたくない
Radim Cernej、2015

3
@radimはい。実際のデータは変更されません。タグのみがフォーマットされ、インデントされます。
Charles Prakash Dasari、2015

2
UTF8ではうまく機能するが、Unicode XMLファイルのコンテンツではうまく機能しないことに気付きました。
Nayan、2016年

1
@SteveWellens、の代わりに、doc.Declaration.ToString() + doc.ToString()またはを使用して宣言にアクセスできます。詳細については、このリンクを参照してください。doc.Savedoc.ToString
デビッドフランス語

1
名前空間を含めることをお勧めします。これは、ユーザーが以前にあまり使用しなかったクラスの名前空間を探す必要がなくなるためです。System.Xml.Linqを使用します。ありがとうございます!
Scott Moniz、

61

これは、クリストファージョンソンからのヒープの方が優れています。

  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 version="1.0" encoding="UTF-8" ?>、上部の行なしで)XMLフラグメントを渡したところ、問題なく動作しました。
Simon Tewsi 2013

3
受け入れられた答えと比較して。チャールズと比較して、これは設定可能性が優れています。しかし、私はおそらく将来的に自分でCharliesメソッドを使用するでしょう。そのような構成可能性はまれな要件です。
2013年

1
これははるかに良くて短くなっています
Alex Jolig

8

私のために働いている簡単な解決策:

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

これにより、<?xml version = "1.0" encoding = "utf-16"?>をヘッダーに持つxmlファイルが作成されます。これはXmlSerializerによって解析されず、エラー「Unicodeバイトオーダーマークがありません」が表示されました。修正はencoding = "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
私にとってはうまくいきました。私はそれを文字列の拡張メソッドにしました。また、そのウェブサイトがダウンしているので、コピーを手に入れて良かったです...
goodguys_activate

1
回答が重複しています。@SM Kamranも同じ答えを投稿します。
Vahid Farahmandian

@VahidFarahmandianはい。私は彼より1分早く投稿したので、私はそれについて多くをすることができませんでした:)ところで、私はブログのポスターに信用を与えるために答えがどこから来たかを追加しようとしました。残念ながら、リンクは現在壊れている:(。
Chansikイム

Charles(FormatXml)やTodd(PrettyXml)の回答と比較すると、この回答<?xml...?>は行を取り除いていないので、私はこの回答が一番好きです。この答えは、私が最初に考えていたものを取得します。唯一の欠点は、ネイティブで使用されるスペースではなくタブを使用することです。私は設定しIndentation = 1IndentChar = '\t'私が欲しかったものを正確に取得しました。
サラウェインバーガー

@ 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

UTF-8 XML宣言によるカスタマイズ可能なPretty XML出力

次のクラス定義は、XML宣言をUTF-8として使用して、入力XML文字列をフォーマットされた出力XMLに変換する簡単な方法を示しています。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を使用させるのではなく、生のテキストの解析をサポートするメソッドを追加できます。私の場合、XmlDocumentを使用してXMLを操作する必要があったため、これを追加しませんでした。

使用法:

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.