.NET で XML を文字列から読み込んでみた

ファイル、ストリームからなら簡単にできるんだけど、文字列からというのがよく分からなかったのでやってみた…のがこちら。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;


namespace demoXmlValidate {


    /// <summary>
    ///
    /// </summary>
    class EntryPoint {
        /// <summary>
        ///
        /// </summary>
        public void run() {
            string result_data = readFromFile( "hello.gccproj" );

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.NameTable = new NameTable();

            XmlNamespaceManager manager = new XmlNamespaceManager( settings.NameTable );
            XmlParserContext context = new XmlParserContext( settings.NameTable, manager, "ja", XmlSpace.Default );
            XmlReader reader = XmlReader.Create( new XmlTextReader( result_data, XmlNodeType.Document, context ), settings );

            XmlDocument document = new XmlDocument();
            XmlNode current;
            XmlAttribute attribute;
            Stack<XmlNode> node_stack = new Stack<XmlNode>();

            node_stack.Push( document );
            while ( reader.Read() ) {
                if ( reader.NodeType == XmlNodeType.Whitespace )
                    continue;

                if ( reader.HasValue ) {
                    if ( reader.Name != string.Empty )
                        Console.WriteLine( "{0}:{1} => {2}", reader.Name, reader.NodeType, reader.Value );
                    else
                        Console.WriteLine( "    :{0} => {1}", reader.NodeType, reader.Value );
                } else
                    Console.WriteLine( "{0}:{1}", reader.Name, reader.NodeType );

                switch ( reader.NodeType ) {
                    case XmlNodeType.XmlDeclaration:
                        if ( reader.HasAttributes ) {
                            document.AppendChild( document.CreateXmlDeclaration( reader.GetAttribute( "version" ),
                                                                                 reader.GetAttribute( "encoding" ),
                                                                                 "no"
                                                                                 )
                                                  );
                        }
                        break;

                    case XmlNodeType.Element:
                        node_stack.Push( document.CreateElement( reader.Name ) );

                        if ( reader.HasAttributes ) {
                            current = node_stack.Peek();

                            for ( int i = 0; i < reader.AttributeCount; ++i ) {
                                reader.MoveToAttribute( i );

                                attribute = document.CreateAttribute( reader.Name );
                                attribute.Value = reader.Value;

                                current.Attributes.Append( attribute );
                            }
                        }

                        if ( reader.IsEmptyElement ) {
                            foldElement( node_stack );
                        }
                        break;

                    case XmlNodeType.Text:
                        current = node_stack.Peek();
                        current.AppendChild( document.CreateTextNode( reader.Value ) );
                        break;

                    case XmlNodeType.EndElement:
                        foldElement( node_stack );
                        break;
                }
                Console.WriteLine( "stack count: {0}", node_stack.Count );
            }

            document.Save( "hello.validated.xml" );
        }


        /// <summary>
        /// スタックからノードを 2 つ取り出して畳み込みます。
        /// </summary>
        /// <param name="stack"></param>
        private void foldElement(Stack<XmlNode> stack) {
            XmlNode current, parent;

            if ( stack.Count > 1 ) {
                current = stack.Pop();
                parent = stack.Pop();

                parent.AppendChild( current );
                Console.WriteLine( "append {0} to {1}", parent.Name, current.Name );
                stack.Push( parent );
            }
        }


        /// <summary>
        /// 指定されたファイルのすべての内容を返します。
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private string readFromFile(string filename) {
            using ( StreamReader reader = new StreamReader( File.OpenRead( filename ) ) ) {
                return reader.ReadToEnd();
            }
        }


        /// <summary>
        /// プログラムのエントリポイントです。
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args) {
            EntryPoint progn = new EntryPoint();

            progn.run();
        }
    }
}