从父节点信息创建XML

时间:2012-02-07 15:32:54

标签: c# xml linq-to-xml

我有一个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树。截至目前,我已经为leve2,level21,level22,level31提供了单独的XElements。但是我如何创建XML,但是从上面的parentid信息中以XML格式添加这些元素?

<level1>
  <level2>
      <level21 attrib1 ="val1" attrib2="val2"/>
      <level22 attrib1 ="val1" attrib2="val2"/>
  </level2>
  <level3>
       <level31 attrib1 ="val1" attrib2="val2"/>
  </level3>
</level1>

2 个答案:

答案 0 :(得分:0)

我不知道attrib1attrib2属性的价值来自哪里。但就输出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构建每个节点时,可以包含节点属性的值。

答案 1 :(得分:0)

你可以这样做:

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>