친숙한 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
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 프레임 워크 pre-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 ()에서 { "닫힌 스트림에 액세스 할 수 없습니다."}와 같은 오류가 발생합니다. pls는 해결책을 제공합니다.
Jatin Gadhiya

@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 2019

3
@radim 예. 실제 데이터는 변경되지 않습니다. 태그 만 형식화되고 들여 쓰기됩니다.
Charles Prakash Dasari

2
UTF8에서는 잘 작동하지만 유니 코드 XML 파일 내용에서는 작동하지 않는 것으로 나타났습니다.
Nayan

1
@SteveWellens의 경우 doc.Declaration.ToString() + doc.ToString()또는 doc.Save대신에 를 사용하여 선언에 액세스 할 수 있습니다 doc.ToString. 자세한 내용은 이 링크 를 참조하십시오.
David French

1
사용자가 이전에 많이 사용하지 않았던 클래스의 네임 스페이스를 찾아 보지 못하도록 네임 스페이스를 포함하도록 제안하십시오. 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 version="1.0" encoding="UTF-8" ?>, 맨 위에 줄이 없는) XML 조각을 전달 했으며 정상적으로 작동했습니다.
Simon Tewsi

3
허용 된 답변과 비교합니다. Charles와 비교하면이 구성이 더 좋습니다. 그러나 아마도 미래에는 Charlies 방법을 사용할 것입니다. 이러한 구성 가능성은 거의 필요하지 않습니다.
Todd

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에서 구문 분석되지 않았으며 '유니 코드 바이트 순서 표시가 없습니다'라는 오류가 발생했습니다. 수정은 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
나를 위해 잘 작동합니다. 방금 문자열의 확장 방법으로 만들었습니다. 또한 그 웹 사이트가 다운되었으므로 사본을
빼앗는

1
중복 된 답변. @SM Kamran도 같은 답변을 게시합니다.
Vahid Farahmandian

@VahidFarahmandian 예. 나는 그보다 1 분 일찍 게시했기 때문에 그것에 대해 많은 것을 할 수 없었습니다. 불행히도, 링크는 이제 끊어졌습니다 :(.
Chansik Im

Charles (FormatXml) 및 Todd (PrettyXml)의 답변과 비교 하여이 답변이 가장 좋습니다. 왜냐하면이 답변이 <?xml...?>줄을 벗기지 않기 때문 입니다. 이 대답은 내가 원래 생각했던 것을 얻습니다. 유일한 단점은 기본적으로 사용되는 공백보다 탭을 선호한다는 것입니다. 나는 내가 원하는 것을 정확하게 설정 Indentation = 1하고 IndentChar = '\t'얻었습니다.
Sarah Weinberger '

@ CHICoder007 확장 방법에 대한 의견에 감사드립니다. 나 한테 새로운 걸 가르쳐 줬어 (this String XML)작품에 추가하면 좋습니다.
사라 와인 버거

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.