Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于子元素值LINQ选择父XML(整个层次结构)元素_C#_Linq - Fatal编程技术网

C# 基于子元素值LINQ选择父XML(整个层次结构)元素

C# 基于子元素值LINQ选择父XML(整个层次结构)元素,c#,linq,C#,Linq,我有下面的XML和通过ID的查询,如何获得父层次结构 <Child> <Child1 Id="1"> <Child2 Id="2"> <Child3 Id="3"> <Child4 Id="4"> <Child5 Id="5"/> <Child6 Id="6"/

我有下面的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查找父元素,那么如何获得具有层次结构的以下输出

<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 ;)
}
stringxml=@”
";
TextReader tr=新的StringReader(xml);
XDocument doc=XDocument.Load(tr);
可数myList=
从文件中的el.subjects()开始
其中(字符串)el.Attribute(“Id”)==“4”//here任意
选择el;
//以某种方式选择你的英雄元素
XElement hero=myList.FirstOrDefault();
foreach(hero.祖先()中的XElement祖先)
{
Console.WriteLine(祖先.Name);//在单独的文档中重建树,我打印;)
}

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

在Linq To XML中,有一个在该节点上调用的方法

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

但它不会按照您希望的方式转换XML树

你想要的是:

  • 对于给定元素,查找父元素
  • 从父元素中删除除给定元素之外的所有元素
  • 从给定元素中删除所有元素
类似于Linq中的内容(无错误处理):

XDocument doc=XDocument.Parse(“”);
//例如,查找ID为4的元素
XElement el=doc.subjects().First(el=>el.Attribute(“Id”).Value==“4”);
el.RemoveNodes();
XElement parent=el.parent;
parent.RemoveNodes();
添加(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。

      根据提供的示例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;
      }
      
      stringxml=
      @"
      ";
      var doc=XDocument.Parse(xml);
      //假设每个节点都有一个Id属性
      //将有一个值为4的Id
      //否则将引发异常。
      XElement el=doc.Root.subjects().First(x=>x.Attribute(“Id”).Value==“4”);
      //讨论所有子节点
      el.RemoveNodes();
      //走到树上寻找父母;当
      //父节点为null,则当前节点为
      //最顶端的父母。
      while(true)
      {
      如果(el.Parent==null)
      {
      打破
      }
      el=el.父母;
      }
      
      您尝试过什么吗?我正在尝试,但到目前为止没有成功。这个问题似乎更适合递归算法,而不是linq。对于您的情况,我不知道在我的真实示例中它在哪个级别包含id。无论如何,感谢您在我的示例中的响应,部分并不重要,它只是说明如何获得给定的元素。我将编辑答案以指出这一点。
      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;
      }