0

解析して IEnumerable として返す XML 構造があります。

 <menuItem Id="1">
      <menuItem Id="2">
            <menuItem Id="5">
                  <menuItem Id="9">
                       <criterion></criterion>
                  </menuItem>
             </menuItem>
       </menuItem>
  </menuItem>
  <menuItem Id="10>
    /// huge xml document from here on...

このクラスを使用して解析します。

 public static  class XmlConverter
{

    public static IEnumerable<MenuItem> Parser()
    {
        using (var fileStream = new FileStream(HttpContext.Current.Server.MapPath("~/DataSource/MenuNavigation.xml"), FileMode.Open))
        {
            return Read(fileStream);
        }
    }

    private static IEnumerable<MenuItem> Read(Stream stream)
    {
        return (IEnumerable<MenuItem>)XmlSerializer().Deserialize(stream); ;
    }


    private static XmlSerializer XmlSerializer()
    {
        return new XmlSerializer(typeof(List<MenuItem>), GetXmlRootAttribute());

    }

    private static XmlRootAttribute GetXmlRootAttribute()
    {
        return new XmlRootAttribute() { ElementName = "Navigation", IsNullable = true };
    }
}

次のオブジェクトに解析されます。

  public class MenuItem
{
    [XmlAttribute("Id")]
    public int Id { get; set; }
    [XmlAttribute("Name")]
    public string Name { get; set; }
    [XmlAttribute("Description")]
    public string Description { get; set; }
    [XmlAttribute("Link")]
    public string Link { get; set; }
    [XmlAttribute("Role")]
    public string RoleId { get; set; }
    [XmlAttribute("Alert")]
    public string Alert { get; set; }
    [XmlElement("Criterion")]
    public List<Criterion> Criteria { get; set; }

    private List<MenuItem> _menuItems = new List<MenuItem>();

    [XmlElement("MenuItem")]
    public MenuItem[] MenuItems
    {
        get { return _menuItems.ToArray(); }
        set
        {
            _menuItems.Clear();
            if (value != null)
            {
                _menuItems.AddRange(value);
            }
        }
    }
}

返された IEnumerable で Linq クエリを実行すると、次のように使用します。

 var criteria = menuItems.Where(x => x.Id == menuItem.Id)
                         .Select(x => x.Criteria)
                         .FirstOrDefault();

問題は、ここの IEnumerable に 14 項目しかないことです。親アイテムのものなので、Id == 9 を探している場合、Id 1 のサブ要素であるため見つかりません。

問題の Id の親だけでなく、menuItem という名前の要素で各レベルをチェックするように、上記の linq ステートメントを編集するにはどうすればよいですか?

アップデート:

IEnumerable は次のようになります。

  Count=14
 +MenuItem //nested menuItem
  Name
4

1 に答える 1

1

最初に階層を作成することができflattenます (linq は本質的にそれをサポートしていません)。

たとえば、LINQ to Entity を使用して再帰的にネストされたエンティティを選択するにはどうすればよいですか

...その後

var item = menuItems.Flatten(y => y.MenuItems).Where(x => x.Id == 5)
    .FirstOrDefault();
于 2013-03-28T19:31:55.350 に答える