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



我有以下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>

在本例中,如果我查询(Id = 4)并在特定元素中使用Linq找出父元素,如何使用Hierarchy获得以下输出。

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

假设只需要一个节点父树:

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 ;)
}

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

根据所提供的示例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;
}

在Linq to XML中有一个方法叫做AncestorsAndSelf on 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,最后一个也删除属性。
  • 也从所选元素中移除节点。

我找到了以下方法

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);
        }

返回或打印elementNode

最新更新