Nephilim
Nephilim

Reputation: 524

XPath max function and the use of brackets

Let's say we have the following XML:

<people>
  <student name="Peter">
    <subject>
      <name>English</name>
      <grade>60</grade>
    </subject>
    <subject>
      <name>Programming</name>
      <grade>70</grade>
    </subject>
    <diploma>80</diploma>
  </student>
</people>

What we're trying to find is the "name" of the "subject" where "Peter" has the largest number in "Grade". The entire XML has a few more people with different names but I dont think that matters. It all follows the same principle.

How come this XPath fails:

people/student[@name="Peter"][max(subject/grade)]/subject/name

The error is called:

NO MATCH!

I've never been able to use the max function correctly if I had to print out a different value after calculating the maximum value.

I've also spent quite a few minutes on XMLLINT trying to make it work in Xpath1.0

xmllint --xpath 'people/student[name='Peter'][not(subject/grade > subject/grade)]/subject/grade' grades.xml >result.txt

This returns:

XPath set is empty

I've read up on the functions, so I would appreciate code examples and not links to documentations. If you find an XML error there's probably been an issue when I was manually translating this into english.

EDIT:

people/student[@name="Peter"]/max(subject/grade)

Worked fine and outputted the correct maximum value. Which leads me to believe the problem is with my usage of [] .

Upvotes: 1

Views: 1491

Answers (2)

Daniel Haley
Daniel Haley

Reputation: 52858

Your use of max() didn't work because you aren't comparing max() to anything.

Here are a couple of options...

XPath 2.0

/people/student[@name="Peter"]/subject[grade = max(../subject/grade)]/name

XPath 1.0

/people/student[@name="Peter"]/subject[not(preceding-sibling::subject/grade > grade) and not(following-sibling::subject/grade > grade)]/name

Note that xmllint only supports XPath 1.0.

Upvotes: 1

Jorge Y.
Jorge Y.

Reputation: 1133

I have tried this one with this parser and it returns "Programming". Not sure if it will work with the one you are using:

people/student[@name="Peter"]/subject[number(grade) = max(/people/student[@name="Peter"]/subject/number(grade))]/name

Upvotes: 0

Related Questions