views:

78

answers:

3

Hello everyone, I'm new to Linq and having some strange results when I try to perform a query using where.

Example of the xml:

    <movies>
      <movie id="1">
        <scenes>
          <scene id="1">
            <sceneartistsnames>
              <sceneartistname>Artist A</sceneartistname>
            </sceneartistsnames>
          </scene>
          <scene id="2">
            <sceneartistsnames>
              <sceneartistname>Artist B</sceneartistname>
            </sceneartistsnames>
          </scene>
        </scenes>
      </movie>
      <movie id="10">
        <scenes>
          <scene id="1">
            <sceneartistsnames>
              <sceneartistname>Artist B</sceneartistname>
              <sceneartistname>Artist A</sceneartistname>
            </sceneartistsnames>
          </scene>
        </scenes>
      </movie>
    </movies>

Now trying to select all the scenes where Artist A is part of it.

Dim Results = From MovieWithArtist In MoviesXML...<scene> _
              Where MovieWithArtist.<sceneartistsnames>.<sceneartistname>.Value = "Artist A" _
              Select MovieWithArtist

I only get one scene return, and I was expecting two. :(

Now if I change the second scene in the XML to:

<movie id="10">
        <scenes>
          <scene id="1">
            <sceneartistsnames>
              <sceneartistname>Artist A</sceneartistname>
              <sceneartistname>Artist B</sceneartistname>
            </sceneartistsnames>
          </scene>
        </scenes>
      </movie>

Then I get two scenes return.

What I am doing wrong?

Thank you everyone.

A: 

Well, I don't know the VB.NET XML syntax I'm afraid, but this C# works fine:

static void Main()
{
    XDocument doc = XDocument.Load("movies.xml");

    var query = doc.Descendants("scene")
                   .Where(scene => scene.Elements("sceneartistsnames")
                                        .Elements("sceneartistname")
                                        .Any(name => name.Value == "Artist A"));

    foreach (var scene in query)
    {
        Console.WriteLine(scene);
    }
}

It shouldn't be hard to convert that into VB.NET calls to the LINQ extension methods, but I'm afraid you'll need someone else (Jared?) to help with the XML-specific syntax.

Jon Skeet
Thank you Jon, my C# skills are very poor, still I will try to convert your solution to vb.net, thanks for the help Jon.
A: 

another alternative to Jons answer is to use a select many (multiple from's)

  var qry = from x in xe.Descendants("scene")
            from s in x.Descendants("sceneartistname")
            where (string)s == "Artist A"
            select string.Format("Movie ID {0} Scene ID {1} : {2}", (int)x.Parent.Parent.Attribute("id"), (int)x.Attribute("id"), (string)s);
Tim Jarvis
Thank you I should test this way as well.
+1  A: 

For the sake of formatting I will post this as a separate answer:

This is Jon's answer converted to VB.Net using this site.

Private Shared Sub Main()
     Dim doc As XDocument = XDocument.Load("movies.xml")

  Dim query = doc.Descendants("scene").Where(Function(scene) scene.Elements("sceneartistsnames").Elements("sceneartistname").Any(Function(name) name.Value = "Artist A"))

     For Each scene In query
         Console.WriteLine(scene)
     Next
    End Sub
orandov
Thank you orandov, it works perfect. I marked Jon answer correct. Still thank you for your help.