深入理解 c# 第十四章 一個通過 ExpandoObject實現簡單XML DOM 變換 建立DOM樹

eyetired發表於2018-05-20
    class ExpandoXml
    {
        public static dynamic CreateDynamicXml(XElement element)
        {
            dynamic expando = new ExpandoObject();
//{System.Dynamic.ExpandoObject}			
            expando.XElement = element;
            expando.ToXml = (Func<string>)element.ToString;

            IDictionary<string, object> dictionary = expando;
			//{System.Dynamic.ExpandoObject}
            foreach (XElement subElement in element.Elements())
            {
//subElement				
//<book name="Mortal Engines">  <author name="Philip Reeve" /></book>				
//<author name="Philip Reeve" />
//<books>  <book name="Mortal Engines">    <author name="Philip Reeve" />  </book>  <book name="The Talisman">    <author name="Stephen King" />    <author name="Peter Straub" />  </book>  <book name="Rose">    <author name="Holly Webb" />    <excerpt>      Rose was remembering the illustrations from      Morally Instructive Tales for the Nursery.    </excerpt>  </book></books>
//<book name="The Talisman">  <author name="Stephen King" />  <author name="Peter Straub" /></book>
//等等
                dynamic subNode = CreateDynamicXml(subElement);
				//{System.Dynamic.ExpandoObject}
                string name = subElement.Name.LocalName;
				//"author"  "book"
                string listName = name + "List";
				//"authorList"  "bookList"
                if (dictionary.ContainsKey(name))
                {
                    ((List<dynamic>) dictionary[listName]).Add(subNode);
                }
                else
                {
                    dictionary[name] = subNode;
                    dictionary[listName] = new List<dynamic> { subNode };
                }
            }
            return expando;
        }

        static void Main()//一個通過 ExpandoObject實現簡單XML DOM 變換 建立DOM樹
        {
            XDocument doc = XDocument.Load("books.xml");
//<books>  <book name="Mortal Engines">    
//<author name="Philip Reeve" />  </book>  <book name="The Talisman">    
//<author name="Stephen King" />    <author name="Peter Straub" />  
//</book>  <book name="Rose">    <author name="Holly Webb" />    
//<excerpt>      Rose was remembering the illustrations from      
//Morally Instructive Tales for the Nursery.    </excerpt>  </book></books>			
            dynamic root = CreateDynamicXml(doc.Root);
            Console.WriteLine(root.book.author.ToXml());
            Console.WriteLine(root.bookList[2].excerpt.XElement.Value);
        }
    }


books.xml
<books>
  <book name="Mortal Engines">
    <author name="Philip Reeve" />
  </book>
  <book name="The Talisman">
    <author name="Stephen King" />
    <author name="Peter Straub" />
  </book>
  <book name="Rose">
    <author name="Holly Webb" />
    <excerpt>
      Rose was remembering the illustrations from
      Morally Instructive Tales for the Nursery.
    </excerpt>
  </book>
</books>


建立DOM樹
  用expando建立一顆XML DOM的映象樹。
樹的每個節點都有兩個名/值對:XElement---儲存用於建立節點的原始LINQ to XML元素,
ToXml---儲存返回節點XML字串的委託。可以僅僅呼叫node.XElement.ToString()
返回字串,但這次我們要使用ExpandoObject和委託。需要指出的是,我們將使用ToXml
來代替ToString,因為設定expando的ToString屬性時不能覆蓋普通的ToString方法。這會
引起混淆,因此換了一個名字。
  有趣的部分並不是固定的名稱,而是它依賴於真正的XML。
  用遞迴處理工作。
  
輸出
<author name="Philip Reeve" />


      Rose was remembering the illustrations from
      Morally Instructive Tales for the Nursery.

相關文章