从父节点信息创建XML
本文关键字:XML 创建 信息 父节点 | 更新日期: 2023-09-27 18:22:48
我有一个xml文件,其中包含如下根的信息:usequery属性有一个SQL查询,从中填充XML元素数据。
<ARAXmlFormat>
<root name="level1" index = "1" parentid ="0" haschildren="yes"/>
<root name="level2" index = "2" parentid ="1" haschildren="yes" usequery="query2"/>
<root name="level21" index = "3" parentid ="2" haschildren="no" usequery="query1"/>
<root name="level22" index = "4" parentid ="2" haschildren="no" usequery="query3"/>
<root name="level3" index = "5" parentid ="1" haschildren="yes"/>
<root name="level31" index = "6" parentid ="5" haschildren="no" usequery="query4"/>
</ARAXmlFormat>
由此,我需要生成一个XML树,如下所示。到目前为止,我已经有了级别2、级别21、级别22和级别31的单独XElement。但是,我如何创建XML,但按照下面的XML格式从上面的parentid信息中添加这些元素呢?
<level1>
<level2>
<level21 attrib1 ="val1" attrib2="val2"/>
<level22 attrib1 ="val1" attrib2="val2"/>
</level2>
<level3>
<level31 attrib1 ="val1" attrib2="val2"/>
</level3>
</level1>
你可以这样做:
var source = XDocument.Parse(xml); // or whatever
var sourceElems = source.Root.Elements("root");
var result = new XDocument(new XElement("result"));
var resultElems = new Dictionary<int, XElement>();
resultElems.Add(0, result.Root);
foreach (var sourceElem in sourceElems)
{
var resultElem = new XElement((string)sourceElem.Attribute("name"));
int parentId = (int)sourceElem.Attribute("parentid");
resultElems[parentId].Add(resultElem);
resultElems.Add((int)sourceElem.Attribute("index"), resultElem);
}
基本上,遍历元素,在字典中找到每个元素的父元素,将其作为子元素添加到该父元素,最后将其添加到字典中,这样它就可以成为父元素本身。这假设父级总是在其所有子级之前声明。
使用源数据,它会创建以下结果:
<result>
<level1>
<level2>
<level21 />
<level22 />
</level2>
<level3>
<level31 />
</level3>
</level1>
</result>
我不知道attrib1
和attrib2
属性的值从哪里来。但是,就输出XML树的层次结构而言,您可以递归地构建它,使用以下方法:
var doc = XDocument.Load("roots.xml"); // read input xml file
Func<int, IEnumerable<XElement>> selectChildNodes = null; // declare delegate
selectChildNodes = parentId => doc.Elements("ARAXmlFormat").Elements().Where(
p => p.Attribute("parentid").Value == parentId.ToString()
).Select(
x => new XElement(
x.Attribute("name").Value,
selectChildNodes(Convert.ToInt32(x.Attribute("index").Value))
)
);
IEnumerable<XElement> levels = selectChildNodes(0);
此解决方案的工作方式与输入文件中<root>
元素的顺序无关。selectChildNodes
是一个委托,它接受父节点的索引作为输入参数,并递归地返回该元素的所有子节点。输出是这样的,没有属性:
<level1>
<level2>
<level21 />
<level22 />
</level2>
<level3>
<level31 />
</level3>
</level1>
当用new XElement
构造每个节点时,可以包含节点属性的值。