LINQ to XML:创建复杂的匿名类型

时间:2011-06-08 20:48:26

标签: linq-to-xml anonymous-objects

我有一个xml文件,如下所示:

<ProductGroup>
  <Product id="4601A">
    <name>Roses</name>
    <section>Floral</section>
    <price>46</price>
    <PopupImages>
      <PopupImage>img1.jpg</PopupImage>
      <PopupImage>img2.jpg</PopupImage>
    </PopupImages>
    <ImageThumbs>
      <thumb>img1-thm.jpg</thumb>
      <thumb>img2-thm.jpg</thumb>
    </ImageThumbs>
  </Product>
</ProductGroup>

在生产环境中,ProductGroup节点可能包含许多Product节点。为此,我想构建一个具有以下属性的匿名对象列表:

name 
section
image
thumb

我可以使用XDocument获取Product元素列表。

Dim doc As XDocument = XDocument.Load("ProductsGroups.xml")
Dim lstProducts = from x In doc Where CType(c.Element("price"), Integer) < 54

从这里我该怎么办?

更新

让我更好地解释一下。我不确定我是否正确地传达了这一点。

以上面的xml示例为例。我编写的上述代码返回具有指定“where”条件的所有产品元素。现在返回每个 XmlElement(产品)我要创建n个匿名对象。数字n取决于PopupImages和ImageThumbs节点的子节点数。然而,在我的情况下,数字将是相同的。因此回到上面的例子,我会得到两个匿名对象:

        Anonymous1      Anonymous2
        ----------      ----------
name        Roses           Roses
section     Floral          Floral
image       img1.jpg        img2.jpg
thumb       img1-thm.jpg    img2-thm.jpg

2 个答案:

答案 0 :(得分:1)

尝试这种方法:

Dim query = From product In doc.Elements("Product") 
            Where Integer.Parse(product.Element("price").Value) < 54 
            Select New With
            {
                .Name = product.Element("name").Value,
                .Section = product.Element("section").Value, 
                .Images = product.Descendants("PopupImage").Select(Function(i) i.Value), 
                .Thumbs = product.Descendants("thumb").Select(Function(t) t.Value) 
            }

For Each item in query
    Console.WriteLine(item.Name)
    Console.WriteLine(item.Section)
    Console.WriteLine("Images:")
    For Each image in item.Images
        Console.WriteLine("  " + image)
    Next
    Console.WriteLine("Thumbs:")
    For Each thumb in item.Thumbs
        Console.WriteLine("  " + thumb)
    Next
Next

如果你真的需要一个列表,只需调用query.ToList()并将结果存储在一个变量中,或将原始查询括在括号中并附加ToList()(为了便于阅读,我不想这样做)。同样,图像和缩略图目前的类型为IEnumerable<string>,因此如果您需要列表或数组,请添加相应的扩展方法调用。

答案 1 :(得分:0)

我不熟悉VB.Net,但在C#中你会写这样的东西:

        XDocument doc = XDocument.Load("D:\\file.xml");
        var lstProducts = from XElement elem in doc.Element("ProductGroup").Elements("Product")
                          where int.Parse(elem.Element("price").Value) < 54
                          select new
                          {
                              name = elem.Element("name").Value,
                              section = elem.Element("section").Value,
                              image = elem.Element("PopupImages").Element("PopupImage").Value,
                              thumb = elem.Element("ImageThumbs").Element("thumb").Value
                          };

希望这有帮助。

编辑:应该处理合并PopupImages和ImageThumbs的新查询:

       var lstProducts = from XElement elem in doc.Element("ProductGroup").Elements("Product")
                          where int.Parse(elem.Element("price").Value) < 54

                          let images = elem.Element("PopupImages").Elements("PopupImage")
                          let thumbs = elem.Element("ImageThumbs").Elements("thumb")

                          from img in images.Select(
                            (im, idx) => new KeyValuePair<string, string>(im.Value, thumbs.ElementAt(idx).Value)
                          )

                          select new
                          {
                              name = elem.Element("name").Value,
                              section = elem.Element("section").Value,
                              image = img.Key,
                              thumb = img.Value
                          };

仍在C#中,但我认为这个想法很明确。