2009-10-23 3 views
2

저는 LINQ to XML을 사용하여 간단한 XML 파일 파서를 작성했습니다.Linq to XML 리팩터링을 사용하여 딥 객체 그래프를 만드시겠습니까?

XML의 각 요소에 대해 TreeNode 객체 (즉 간단한 트리 구조)를 갖고 싶습니다. 각 요소를 강하게 입력하고 싶습니다.

System.XML을 사용하여 이전에 사용한 단순한 루핑 방식과 비교할 때보기 흉하고 복잡합니다. 여기서 중복을 제거 할 수있는 방법이 있습니까? 수업 및 소스 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

답변

1

예제 데이터와 실제 유형이 없어도이 내용을 완전히 대답하기는 어렵지만 아래와 같이 리펙토링합니다.

원래 예제에서 엔티티 (Agent 등)의 생성자를 엉망으로 만들고 싶지는 않지만 별도의 "TreeNode<T>"모델을 유지하고 트리 내부에 엔티티를 넣고 싶다고 가정합니다. (관련 컬렉션으로 모델을 만들기 위해 엔터티를 변경하는 대신). 프레임 워크와

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 
       ) 
      ) 
     ) 
    ) 
); 

: 나는 또한 우리가 엔티티 수보다 우리가 TreeNode<T> 더 많은 자유를 걸릴 수 있으므로이 LINQ 하위 쿼리와 함께 사용할 수 있기 때문에 내가 IEnumerable<...>을 받아들이는 생성자를 도입 한 것으로 가정 한 아래 코드를 입력하십시오 :

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") 
      })) 
     })) 
    }; 

을 :

<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; } 
}