blbec
blbec

Reputation: 21

XML Xpath expression

I am trying to get the elements title and runtime (siblings) where the runtime value is larger than the input value. My C# code with the XPath expression is:

ElementValue = 140;

nodeList = root.SelectNodes(@"/moviedb/movie[./runtime>'" + ElementValue + "'/title | /moviedb/movie[./runtime>'" + ElementValue + "']/runtime");

This XPath expression is not returning anything.

My XML file:

  <moviedb>
      <movie>
        <imdbid>tt0120689</imdbid>
        <genres>Crime,Drama,Fantasy,Mystery</genres>
        <languages>English,French</languages>
        <country>USA</country>
        <rating>8.5</rating>
        <runtime>189</runtime>
        <title lang="english">The Green Mile</title>
        <year>1999</year>
      </movie>
      <movie>
        <imdbid>tt0415800</imdbid>
        <genres>Action,Animation,Drama,Thriller</genres>
        <languages>English</languages>
        <country>USA</country>
        <rating>4.5</rating>
        <runtime>139</runtime>
        <title lang="english">Fight Club</title>
        <year>2004</year>
      </movie>
    </moviedb>

Upvotes: 2

Views: 100

Answers (3)

adamretter
adamretter

Reputation: 3517

You can do this using a single XPath expression by performing a union i.e. the | operator. As mentioned in other answers here, you had your select inside your predicate which would not result in the correct answer for you anyway.

Note, if you want to see if a number is bigger than another number, unless you are using a Schema driven data-type aware XQuery engine you will need to cast the text() to a number before performing the comparison. In this instance I have assumed an xs:int will be suitable for you. Also you can use the atomic gt as opposed to = which may be more efficient.

ElementValue = 140;

nodeList = root.SelectNodes(@"/moviedb/movie[xs:int(runtime) gt " + ElementValue + "]/(title | runtime)");

Upvotes: 1

StuartLC
StuartLC

Reputation: 107357

You seem to be applying the values you want off the node as a filter criteria, which won't work. I would go about this another way, first finding the nodes which meet the criteria:

nodeList = root.SelectNodes(@"/moviedb/movie[runtime > " + ElementValue + "]");

And then grabbing the child elements from each:

foreach (var node in nodeList)
{
    Debug.WriteLine(node.SelectSingleNode("title").InnerText);
    Debug.WriteLine(node.SelectSingleNode("runtime").InnerText);
}

Upvotes: 1

Anirudha
Anirudha

Reputation: 32817

You can instead use linq2xml

var doc=XDocument.Load(path);
var movies=doc.Elements("movie")
              .Where(x=>(int)x.Element("runtime")>input)
              .Select(x=>new 
                     {
                         Title=x.Element("title").Value,
                         Runtime=(int)x.Element("runtime")
                     });

You can now iterate over movies

foreach(var movie in movies)
{
    movie.Title;
    movie.Runtime;
}

Upvotes: 2

Related Questions