代码之家  ›  专栏  ›  技术社区  ›  Davy8

执行此LINQ to XML查询的更好方法?

  •  1
  • Davy8  · 技术社区  · 17 年前

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <Root>
      <Category Name="Tasties">
        <Category Name="Pasta">
          <Category Name="Chicken">
            <Recipe Name="Chicken and Shrimp Scampi" />
            <Recipe Name="Chicken Fettucini Alfredo" />
          </Category>
          <Category Name="Beef">
            <Recipe Name="Spaghetti and Meatballs" />
            <Recipe Name="Lasagna" />
          </Category>
          <Category Name="Pork">
            <Recipe Name="Lasagna" />
          </Category>
          <Category Name="Seafood">
            <Recipe Name="Chicken and Shrimp Scampi" />
          </Category>
        </Category>
      </Category>
    </Root>
    

    var q = from chk in
                (from c in doc.Descendants("Category")
                 where c.Attribute("Name").Value == "Chicken"
                 select c)
            select from r in chk.Descendants("Recipe")
                   select r.Attribute("Name").Value;
    
    foreach (var recipes in q)
    {
        foreach (var recipe in recipes)
        {
            Console.WriteLine("Recipe name = {0}", recipe);
        }
    }
    

    IEnumerable<IEnumerable<String>> 当我只想要一个 IEnumerable<String> .

    4 回复  |  直到 17 年前
        1
  •  3
  •   Marc Gravell    17 年前

    就我个人而言,我会使用 XmlDocument SelectNodes :

    foreach(XmlElement el in doc.DocumentElement.SelectNodes(
       "Category[@Name='Tasties']/Category[@Name='Pasta']/Category[@Name='Chicken']/Recipe")) {
        Console.WriteLine(el.GetAttribute("Name"));
    }
    

    var q = from c1 in doc.Root.Elements("Category")
            where c1.Attribute("Name").Value == "Tasties"
            from c2 in c1.Elements("Category")
            where c2.Attribute("Name").Value == "Pasta"
            from c3 in c2.Elements("Category")
            where c3.Attribute("Name").Value == "Chicken"
            from recipe in c3.Elements("Recipe")
            select recipe.Attribute("Name").Value;
    foreach (string name in q) {
        Console.WriteLine(name);
    }
    

        string[] categories = { "Tasties", "Pasta", "Chicken" };
        XDocument doc = XDocument.Parse(xml);
        IEnumerable<XElement> query = doc.Elements();
        foreach (string category in categories) {
            string tmp = category;
            query = query.Elements("Category")
                .Where(c => c.Attribute("Name").Value == tmp);
        }
        foreach (string name in query.Descendants("Recipe")
            .Select(r => r.Attribute("Name").Value)) {
            Console.WriteLine(name);
        }
    


    编辑以讨论(评论)原因 Where tmp 变量:

    这可能会有点复杂,但我试图公正地回答这个问题;p

    foreach

    class SomeWrapper {
        public string category;
        public bool AnonMethod(XElement c) {
            return c.Attribute("Name").Value == category;
        }
    }
    ...
    SomeWrapper wrapper = new SomeWrapper(); // note only 1 of these
    using(var iter = categories.GetEnumerator()) {
        while(iter.MoveNext()) {
            wrapper.category = iter.Current;
            query = query.Elements("Category")
                 .Where(wrapper.AnonMethod);
        }
    }
    

    哪里 category (通过谓词 AnonMethod ( 内部范围

    class SecondWrapper {
        public string tmp;
        public bool AnonMethod(XElement c) {
            return c.Attribute("Name").Value == tmp;
        }
    }
    ...
    string category;
    using(var iter = categories.GetEnumerator()) {
        while(iter.MoveNext()) {
            category = iter.Current;
            SecondWrapper wrapper = new SecondWrapper(); // note 1 per iteration
            wrapper.tmp = category;
            query = query.Elements("Category")
                 .Where(wrapper.AnonMethod);
        }
    }
    

        2
  •  1
  •   CoderDennis    17 年前

    var q = from t in doc.Root.Elements("Category")
            where t.Attribute("Name").Value == "Tasties"
            from p in t.Elements("Category")
            where p.Attribute("Name").Value == "Pasta"
            from c in p.Elements("Category")
            where c.Attribute("Name").Value == "Chicken"
            from r in c.Elements("Recipe")
            select r.Attribute("Name").Value;
    
    foreach (string recipe in q)
    {
        Console.WriteLine("Recipe name = {0}", recipe);
    }
    

    select IEnumerable<IEnumerable<String>>

        3
  •  1
  •   Joel Mueller    17 年前

    如果你 add a using statement 对于系统。Xml。XPath,它将向XDocument添加XPathSelectElements()扩展方法。如果您更熟悉XPath语句,这将允许您使用XPath语句选择节点。

    < < 字符串 >> < 字符串 >

    IEnumerable<IEnumerable<String>> foo = myLinqResults;
    IEnumerable<string> bar = foo.SelectMany(x => x);
    
        4
  •  1
  •   OdeToCode    17 年前

    虽然有点晚,但扩展方法确实可以帮助清理看起来混乱的LINQtoXML查询。对于你的场景,你可以使用这样的代码:

    var query = xml.Root
                   .Category("Tasties")
                   .Category("Pasta")
                   .Category("Chicken")
                   .Recipes();
    

    …使用我展示的一些技巧 From LINQ To XPath And Back Again

    推荐文章