如何使用数据表在C#中构建数据层次结构
我正在进行一个练习,尝试从用户输入到表中的数据手动生成一个XML文件。下面是一个示例表: 注意,在我稍后的代码示例中,为了将来的目的,将公开比此表更多的字段。如何使用数据表在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
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中添加/更新数据。为什么不使用序列化?我不会使用递归,复杂情况下堆栈溢出的可能性太高