2009-10-23 59 views
2

我正在使用LINQ to XML編寫一個簡單的XML文件分析器。使用Linq to XML創建一個深層對象圖,重構?

我想爲XML中的每個元素都有一個TreeNode對象(即一個簡單的Tree結構)。我希望每個元素都是強類型的。

與我之前使用的簡單循環方法(使用System.XML)相比,它看起來很醜陋和多餘。有沒有辦法在這裏消除冗餘?

 XElement ops = XElement.Load(@"c:\temp\exp.xml"); 
     Tree<Element> domain = new Tree<Element>(); 
     domain.Root = new TreeNode<Element>(); 
     var cells = 
        from cell in ops.Elements("cell") 
        select new 
        { 
         TreeNodeObj = new TreeNode<Element> 
          (new Cell((string)cell.Attribute("name"), (string)cell.Attribute("name"), null)), 
         XElem = cell 
        }; 
     foreach (var cell in cells) 
     { 
      domain.Root.AddChild(cell.TreeNodeObj); 
      var agents = 
        from agent in cell.XElem.Elements("agent") 
        select new 
        { 
         TreeNodeObj = new TreeNode<Element> 
          (new Agent((string)agent.Attribute("name"), (string)agent.Attribute("name"), null)), 
         XElem = agent 
        }; 
      foreach (var agent in agents) 
      { 
       cell.TreeNodeObj.AddChild(agent.TreeNodeObj); 
       var nas = 
        from na in agent.XElem.Elements("node-agent") 
        select new 
        { 
         TreeNodeObj = new TreeNode<Element> 
          (new NodeAgent((string)na.Attribute("name"), (string)na.Attribute("name"), null)), 
         XElem = agent 
        }; 
       foreach (var na in nas) 
       { 
        agent.TreeNodeObj.AddChild(na.TreeNodeObj); 
       } 
      } 
     } 
+2

也許你應該提供exp.xml或至少一些示例數據,以便人們可以篡改真實數據。 – Max 2009-10-26 09:20:57

回答

1

如果沒有示例數據和實際類型,很難回答這個問題,但我會像下面那樣重構它。我假設我們不想混淆實體的構造函數(Agent等),並且我們希望保留單獨的「TreeNode<T>」模型,將我們的實體放入樹中(而不是將實體更改爲將事物建模爲關聯的集合)。我也認爲我們能比我們能與實體採取更多的調戲TreeNode<T>,所以我介紹了接受IEnumerable<...>構造,因爲這允許使用LINQ子查詢中使用:

XElement ops = XElement.Load(@"c:\temp\exp.xml"); 
Tree<Element> domain = new Tree<Element>(
    from cell in ops.Elements("cell") 
    select new TreeNode<Element>(
     new Cell(
      (string)cell.Attribute("name"), 
      (string)cell.Attribute("name"), null 
     ), 
     from agent in cell.Elements("agent") 
     select new TreeNode<Element>(
      new Agent(
       (string)agent.Attribute("name"), 
       (string)agent.Attribute("name"), null 
      ), 
      from na in agent.Elements("node-agent") 
      select new TreeNode<Element>(
       new NodeAgent(
        (string)na.Attribute("name"), 
        (string)na.Attribute("name"), null 
       ) 
      ) 
     ) 
    ) 
); 

隨着框架代碼如下:

using System.Collections.Generic; 
using System.Linq; 
using System.Xml.Linq; 
class Tree<T> 
{ 
    public TreeNode<T> Root { get; set; } 
    public Tree() { } 
    public Tree(IEnumerable<TreeNode<T>> children) 
    { 
     Root = new TreeNode<T>(children); 
    } 
} 
class TreeNode<T> 
{ 
    private List<TreeNode<T>> children; 
    public IList<TreeNode<T>> Children 
    { 
     get 
     { 
      if (children == null) children = new List<TreeNode<T>>(); 
      return children; 
     } 
    } 
    private readonly T value; 
    public TreeNode() { } 
    public TreeNode(T value) { this.value = value; } 
    public TreeNode(T value, IEnumerable<TreeNode<T>> children) 
      : this(children) 
    { 
     this.value = value; 
    } 
    public TreeNode(IEnumerable<TreeNode<T>> children) 
    { 
     children = new List<TreeNode<T>>(children); 
    } 
} 
class Element { } 
class Cell : Element { 
    public Cell(string x, string y, string z) { } 
} 
class Agent : Element { 
    public Agent(string x, string y, string z) { } 
} 
class NodeAgent : Element { 
    public NodeAgent(string x, string y, string z) { } 
} 
static class Program 
{ 
    static void Main() 
    { 
     XElement ops = XElement.Load(@"c:\temp\exp.xml"); 
     Tree<Element> domain = new Tree<Element>(
      from cell in ops.Elements("cell") 
      select new TreeNode<Element>(
       new Cell(
        (string)cell.Attribute("name"), 
        (string)cell.Attribute("name"), null 
       ), 
       from agent in cell.Elements("agent") 
       select new TreeNode<Element>(
        new Agent(
         (string)agent.Attribute("name"), 
         (string)agent.Attribute("name"), null 
        ), 
        from na in agent.Elements("node-agent") 
        select new TreeNode<Element>(
         new NodeAgent(
          (string)na.Attribute("name"), 
          (string)na.Attribute("name"), null 
         ) 
        ) 
       ) 
      ) 
     ); 
    } 
} 
1

沒有你的類和XML源,這是相當辛苦爲你提供你後確切的代碼,但這裏是我怎麼樣構建我的XML解析:

XDocument d = XDocument.Parse(@"<a id=""7""><b><c name=""foo""/><c name=""bar""/></b><b/><b2/></a>"); 
var ae = d.Root; 

var a = new A 
    { 
     Id = (int)ae.Attribute("id"), 
     Children = new List<B>(ae.Elements("b").Select(be => new B 
     { 
      Children = new List<C>(be.Elements("c").Select(ce => new C 
      { 
       Name = (string)ce.Attribute("name") 
      })) 
     })) 
    }; 

由於XML :

<a> 
    <b> 
    <c name="foo"/> 
    <c name="bar"/> 
    </b> 
    <b/> 
    <b2/> 
</a> 

和類:

class A 
{ 
    public int Id { get; set; } 
    public List<B> Children { get; set; } 
} 
class B 
{ 
    public List<C> Children { get; set; } 
} 
class C 
{ 
    public string Name { get; set; } 
}