2009-10-23 71 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; } 
}