首页 > 解决方案 > 使用 Linq 递归查询 XML

问题描述

<tok id="9993" type="group">
  <tok id="144" type="atom" soff="686" eoff="693">
    <txt>popular</txt>
  </tok>
  <tok id="145" type="group">
     <tok id="144" type="atom" soff="686" eoff="693">
       <txt>movie</txt>
     </tok>
     <tok id="145" type="atom" soff="697" eoff="703">
       <txt>characters</txt>
     </tok>
  </tok>
</tok>

我有一个 XML 文档,我需要在其中获取 soff 和 eoff 的值,但这些值可以嵌套。我曾尝试使用 SelectMany(),但我做错了。以上是该文件的摘录。我基本上想获得类型为“atom”的所有“tok”,这样我就可以从每个喜欢的地方获得我需要的两个值。我的查询是这样的:

 var queryHeadsTails2 = from h in xmlDoc.Root.Descendants("tok")
                        where (h.Attribute("id").Value == elem.entityID && h.Attribute("type").Value == "group")
                        select h;

我可以使用 SelectMany 来获取 type = "atom" 的所有行还是有更好的方法?

下面的答案

var groups = xmlDoc.Descendants("tok").Where(x => (string)x.Attribute("type") == "group" && x.Elements("tok").Where(y => (string)y.Attribute("type") == "atom").Any()).Select(x => new {
                        id = (string)x.Attribute("id"),
                        atoms = x.Elements("tok").Where(y => (string)y.Attribute("type") == "atom").ToList()
                    }).ToList();

非常接近,但在这部分失败(尝试获取组 id 153527 的 eoff 和 soff):

<tok id="153619" type="group">
    <tok id="80" type="atom" soff="388" eoff="390">
      <txt>in</txt>
    </tok>
    <tok id="153527" type="group">
      <tok id="153526" type="group">
        <tok id="81" type="atom" soff="391" eoff="396" no-space="true">
          <txt>today</txt>
        </tok>
        <tok id="82" type="atom" soff="396" eoff="398">
          <txt>'s</txt>
        </tok>
      </tok>
      <tok id="128206" type="group">
        <tok id="6360" type="group">
          <tok id="83" type="atom" soff="399" eoff="404">
            <txt>action</txt>
          </tok>
          <tok id="84" type="atom" soff="405" eoff="409">
            <txt>movie</txt>
          </tok>
        </tok>
        <tok id="85" type="atom" soff="410" eoff="418" no-space="true">
          <txt>industry</txt>
        </tok>
      </tok>
    </tok>
  </tok>

在我得到我想要的组之后,有没有办法让它变平?有点像我从上面开始的地方?

标签: c#xmllinq

解决方案


尝试以下:

           var groups = doc.Descendants("tok").Where(x => (string)x.Attribute("type") == "group" && x.Elements("tok").Where(y => (string)y.Attribute("type") == "atom").Any()).Select(x => new { id = (string)x.Attribute("id"), atoms = x.Elements("tok").Where(y => (string)y.Attribute("type") == "atom").ToList() }).ToList();

推荐阅读