根据子元素值LINQ选择父XML(整个层次结构)元素

时间:2013-05-21 10:17:21

标签: c# linq

我有以下XML和查询ID,如何获取父层次结构

<Child>
    <Child1 Id="1">
        <Child2 Id="2">
            <Child3 Id="3">
                <Child4 Id="4">
                    <Child5 Id="5"/>
                    <Child6 Id="6"/>
                </Child4>
            </Child3>
        </Child2>
    </Child1>
</Child>

在此if if查询(Id = 4)并在特定元素中使用Linq找出Parent元素如何使用Hierarchy获取以下输出。

<Child>
    <Child1 Id="1">
        <Child2 Id="2">
            <Child3 Id="3">
                <Child4 Id="4"/>
            </Child3>
        </Child2>
    </Child1>
</Child>

提前致谢。

5 个答案:

答案 0 :(得分:0)

假设您只想要一个节点父树:

string xml = @"<Child>
                <Child1 Id="1">
                  <Child2 Id="2">
                    <Child3 Id="3">
                      <Child4 Id="4">
                        <Child5 Id="5"/>
                        <Child6 Id="6"/>
                      </Child4>
                  </Child3>
                 </Child2>
               </Child1>
             </Child>";

TextReader tr = new StringReader(xml);
XDocument doc = XDocument.Load(tr);

IEnumerable<XElement> myList =
    from el in doc.Descendants()
    where (string)el.Attribute("Id") == "4" // here whatever you want
    select el; 

// select your hero element in some way

XElement hero = myList.FirstOrDefault();

foreach (XElement ancestor in hero.Ancestors())
{
    Console.WriteLine(ancestor.Name); // rebuild your tree in a separate document, I print ;)
}

要搜索树的每个元素,迭代使用不带where子句的select查询检索节点,并为每个元素调用foreach。

答案 1 :(得分:0)

在Linq to XML中,AncestorsAndSelf上有一个名为XElement的方法

  

返回包含此元素的元素的集合,以及   这个元素的祖先。

但它不会以你想要的方式转换你的XML树。

你想要的是:

  • 对于给定元素,找到父
  • 从父级删除所有元素,但删除给定元素
  • 从指定元素中删除所有元素

Linq中的这类内容(无错误处理):

XDocument doc = XDocument.Parse("<xml content>");

//finding element having 4 as ID for example
XElement el = doc.Descendants().First(el => el.Attribute("Id").Value == "4");

el.RemoveNodes();
XElement parent = el.Parent;
parent.RemoveNodes();
parent.Add(el);

<强> [编辑] doc.ToString()必须以字符串形式提供您想要的内容。

<强> [编辑]

  • 使用RemoveNodes代替RemoveAll,最后一个也会移除属性。
  • 也从所选元素中删除节点。

答案 2 :(得分:0)

根据提供的示例XML,您可以在找到相关节点后向上走树以查找父节点:

string xml =
@"<Child>
  <Child1 Id='1'>
    <Child2 Id='2'>
      <Child3 Id='3'>
        <Child4 Id='4'>
          <Child5 Id='5'/>
            <Child6 Id='6'/>
        </Child4>
     </Child3>
   </Child2>
  </Child1>
</Child>";


var doc = XDocument.Parse( xml );

// assumes there will always be an Id attribute for each node
// and there will be an Id with a value of 4
// otherwise an exception will be thrown.
XElement el = doc.Root.Descendants().First( x => x.Attribute( "Id" ).Value == "4" );
// discared all child nodes
el.RemoveNodes();

// walk up the tree to find the parent; when the
// parent is null, then the current node is the 
// top most parent.
while( true )
{
    if( el.Parent == null )
    {
        break;
    }

    el = el.Parent;
}

答案 3 :(得分:0)

以下答案节省了我的一天......谢谢

    XElement elementNode = element.Descendants()
                            .FirstOrDefault(id => id.Attribute("id").Value == "4");
    elementNode.RemoveNodes();
    while (elementNode.Parent != null)
    {
        XElement lastNode = new XElement(elementNode);
        elementNode = elementNode.Parent;
        elementNode.RemoveNodes();
        elementNode.DescendantsAndSelf().Last().AddFirst(lastNode);  
   }

答案 4 :(得分:-1)

我找到了以下方式

XElement elementNode = element.Descendants()
                                .FirstOrDefault(id => id.Attribute("id").Value == "4");
        elementNode.RemoveNodes();
        while (elementNode.Parent != null)
        {
            XElement lastNode = new XElement(elementNode);
            elementNode = elementNode.Parent;
            elementNode.RemoveNodes();
            elementNode.DescendantsAndSelf().Last().AddFirst(lastNode);
        }

return或Print elementNode。