如何使用数据表在C#中构建数据层次结构

如何使用数据表在C#中构建数据层次结构,c#,xml,list,object,hierarchy,C#,Xml,List,Object,Hierarchy,我正在进行一个练习,尝试从用户输入到表中的数据手动生成一个XML文件。下面是一个示例表: 注意,在我稍后的代码示例中,为了将来的目的,将公开比此表更多的字段。 ID | ParentID | Element | DefaultValue | ======================================== 0 | -1 | root | | 1 | 0 | first | SomeData | 2 | 0

我正在进行一个练习,尝试从用户输入到表中的数据手动生成一个XML文件。下面是一个示例表:

注意,在我稍后的代码示例中,为了将来的目的,将公开比此表更多的字段。

ID | ParentID | Element | DefaultValue |
========================================
0  | -1       | root    |              |
1  | 0        | first   | SomeData     |
2  | 0        | second  | OtherData    |
3  | 0        | third   |              |
4  | 3        | firstCh | Child of ID=3| 
========================================
注意2,此表中的数据由用户手动输入到我的windows窗体应用程序上的datagridview控件中。此处不涉及SQL。

ID | ParentID | Element | DefaultValue |
========================================
0  | -1       | root    |              |
1  | 0        | first   | SomeData     |
2  | 0        | second  | OtherData    |
3  | 0        | third   |              |
4  | 3        | firstCh | Child of ID=3| 
========================================
我正在尝试使用C#从中构造一个XML文件,而不使用任何XML类。我试图通过纯字符串操作和格式化来实现这一点,因为如果这个测试成功,我可能会扩展它来做更多的事情,这些事情可能会在我们工作的生产环境中被证明是有用的

我目前的思维模式是迭代每个元素,确定某个ID处的元素是否包含子元素,并从这些子元素中构建一个对象列表。遍历子列表,然后确定子列表中的子元素中是否存在“孙子”。这是我制作的代码类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace XMLtoXSDconverter
{
    class XMLConstruct
    {
        public enum ElementType { None, StringElement, LongElement, BoolElement, DateTimeElement, FloatElement, IntElement, DoubleElement };
        public int id;
        public int parentID;
        public string element;
        public string comment;
        public int minOccurs;
        public int maxOccurs;
        List<XMLConstruct> children;
        int indent = 0;

        public string buildXMLConstruct(int id, int parentId, string element, string comment, ElementType elementType, List<XMLConstruct> children, int minOccurs, int maxOccurs)
        {
            this.id = id;
            this.parentID = parentId;
            this.element = element;
            this.comment = comment;
            this.minOccurs = minOccurs;
            this.maxOccurs = maxOccurs;

            string elementTypeString = string.Empty;
            switch (elementType)
            {
                case ElementType.StringElement: elementTypeString = "xs:string"; break;
                case ElementType.LongElement: elementTypeString = "xs:long"; break;
                case ElementType.IntElement: elementTypeString = "xs:int"; break;
                case ElementType.FloatElement: elementTypeString = "xs:float"; break;
                case ElementType.DoubleElement: elementTypeString = "xs:double"; break;
                case ElementType.DateTimeElement: elementTypeString = "xs:dateTime"; break;
                case ElementType.BoolElement: elementTypeString = "xs:boolean"; break;
                default: elementTypeString = string.Empty; break;
            }

            if (this.id == 0)
                element += "Wrapper";

            //Hiccup here, how would I construct the children elements? Recursion perhaps? These children should come in the List<XSDConstruct>, which may contain children too
            return null;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间XMLtoXSDconverter
{
类XmlConstruction
{
公共枚举元素类型{None、StringElement、LongElement、BooleElement、DateTimeElement、FloateElement、InteElement、DoubleElement};
公共int id;
公共int-parentID;
公共字符串元素;
公共字符串评论;
公共卫生事件;
发生公共事件;
列出儿童名单;
int缩进=0;
公共字符串buildXMLConstruct(int-id、int-parentId、string元素、字符串注释、ElementType-ElementType、列表子项、int-minOccurs、int-maxOccurs)
{
this.id=id;
this.parentID=parentID;
this.element=元素;
this.comment=注释;
this.minOccurs=minOccurs;
this.maxOccurs=maxOccurs;
string elementTypeString=string.Empty;
开关(元件类型)
{
case ElementType.StringElement:elementTypeString=“xs:string”中断;
case ElementType.LongElement:elementTypeString=“xs:long”中断;
case ElementType.inteElement:elementTypeString=“xs:int”中断;
case ElementType.FloatElement:elementTypeString=“xs:float”中断;
case-ElementType.DoubleElement:elementTypeString=“xs:double”中断;
case ElementType.DateTimeElement:elementTypeString=“xs:dateTime”中断;
case ElementType.booleElement:elementTypeString=“xs:boolean”中断;
默认值:elementTypeString=string.Empty;break;
}
if(this.id==0)
元素+=“包装器”;
//打嗝,我该如何构造children元素?也许是递归?这些子元素应该出现在列表中,其中可能也包含子元素
返回null;
}
}
}
我一直在琢磨如何处理这个问题以及如何解决它。正如您所见,读者和我可能的救世主,从这个周五下午的噩梦中,
XSDConstruct
包含了能够从中生成XML和XSD文件所需的大部分字段。有一个
列表
子对象,它可以包含每个元素的子对象,以此类推,明确地要求使用递归


因此,我的问题是,如何将表中的数据读入对象中,以包含一个对象树,深度为n级?

首先想到的是处理
XMLConstruct
构造函数之外的子对象。您应该能够构建如下所示的查找表:

var lookupTable = new Dictionary<int, XMLConstruct>();
// note: this is probably not how you iterate over gridview rows,
// just making a proof of concept:
foreach(var row in gridView)
{
    var xc = GetXmlConstruct(row); // build the construct from the gridvew row
    lookupTable.Add(xc.id, xc);
}
必须初始化
children
属性,否则将出现空指针异常

现在可以像这样遍历树:

// assuming that the element with id=0 is the root element
var rootElement = lookupTable[0];
Traverse(rootElement, "");

// remember, this is just a proof of concept, 
// you probably need to render opening/ending tags etc.
public Traverse(XMLConstruct xc, string indentation)
{
    Console.WriteLine(indentation + xc.Element);
    foreach(var child in xc.Children)
        Traverse(child, indentation + "  ");
}

首先想到的是在
XMLConstruct
的构造函数之外处理子对象。您应该能够构建如下所示的查找表:

var lookupTable = new Dictionary<int, XMLConstruct>();
// note: this is probably not how you iterate over gridview rows,
// just making a proof of concept:
foreach(var row in gridView)
{
    var xc = GetXmlConstruct(row); // build the construct from the gridvew row
    lookupTable.Add(xc.id, xc);
}
必须初始化
children
属性,否则将出现空指针异常

现在可以像这样遍历树:

// assuming that the element with id=0 is the root element
var rootElement = lookupTable[0];
Traverse(rootElement, "");

// remember, this is just a proof of concept, 
// you probably need to render opening/ending tags etc.
public Traverse(XMLConstruct xc, string indentation)
{
    Console.WriteLine(indentation + xc.Element);
    foreach(var child in xc.Children)
        Traverse(child, indentation + "  ");
}
希望这有助于:

Node MakeTree()
{   
    // create root, build subtree and return it
    var node = new Node() {Id = 0, ParentId = -1};
    MakeSubTree(node);
    return node;
}
void MakeSubTree(Node parentNode)
{
    // find all children of parent node (they have parentId = id of parent node)
    var nodes = TableItems.Where(e => e.ParentId == parentNode.Id)
                    .Select(e => new Node {ParentId = e.ParentId, Id = e.Id});

    // build subtree for each child and add it in parent's children collection
    foreach (var node in nodes)
    {
        MakeSubTree(node);
        parentNode.Children.Add(node);             
    }
}
TableItems
是项目的集合。类
节点
定义为:

public class Node
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public List<Node> Children { get; set; } 

    public Node()
    {
        Children = new List<Node>();
    }

}
公共类节点
{
公共int Id{get;set;}
public int ParentId{get;set;}
公共列表子项{get;set;}
公共节点()
{
Children=新列表();
}
}
希望这些帮助:

Node MakeTree()
{   
    // create root, build subtree and return it
    var node = new Node() {Id = 0, ParentId = -1};
    MakeSubTree(node);
    return node;
}
void MakeSubTree(Node parentNode)
{
    // find all children of parent node (they have parentId = id of parent node)
    var nodes = TableItems.Where(e => e.ParentId == parentNode.Id)
                    .Select(e => new Node {ParentId = e.ParentId, Id = e.Id});

    // build subtree for each child and add it in parent's children collection
    foreach (var node in nodes)
    {
        MakeSubTree(node);
        parentNode.Children.Add(node);             
    }
}
TableItems
是项目的集合。类
节点
定义为:

public class Node
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public List<Node> Children { get; set; } 

    public Node()
    {
        Children = new List<Node>();
    }

}
公共类节点
{
公共int Id{get;set;}
public int ParentId{get;set;}
公共列表子项{get;set;}
公共节点()
{
Children=新列表();
}
}

为什么不使用序列化?我不会使用递归,复杂数据集上堆栈溢出的可能性太高序列化是个好主意,是的,但问题是我很难理解子对象。这个应用程序的性能也不是一个问题。我认为你让这对你自己来说更加困难,但如果这是你所能接受的,那就取决于你。我完全有可能让这对我自己来说更加困难。这个XML将转换为XSD,然后我们在java中使用这个XSD以及XJC绑定文件和Ant构建来为我们创建java类。除此之外,我们还发明了一个代码生成器应用程序,将XSD文件转换为Upsert方法,该方法将被Google Web服务调用,以在其DFP和DFA API中添加/更新数据。为什么不使用序列化?我不会使用递归,复杂情况下堆栈溢出的可能性太高