إنشاء رسم بياني الكائن العميق مع LINQ إلى XML، إعادة بيع ديون؟

StackOverflow https://stackoverflow.com/questions/1613569

  •  06-07-2019
  •  | 
  •  

سؤال

وأنا أكتب محلل ملف XML بسيط باستخدام LINQ إلى XML.

وأريد أن يكون كائن TreeNode (أي هيكل شجرة بسيطة) لكل عنصر في XML. أريد كل عنصر إلى أن تكتب بقوة.

ويبدو قبيحة وزائدة عن الحاجة بالمقارنة مع نهج حلقات بسيط كنت تستخدم قبل (باستخدام 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);
                }
            }
        }
هل كانت مفيدة؟

المحلول

ومن الصعب الإجابة على هذا تماما بدون بيانات العينة وأنواع الفعلية، ولكن أود أن ريفاكتور عليه أدناه.

ومن المثال الأصلي، أفترض أننا لا نريد فوضى مع منشئات للكيانات (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
                        )
                    )
                )
            )
        );
    }
}

نصائح أخرى

وبدون الفصول الدراسية و 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; }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top