Skip to content
This repository has been archived by the owner on Aug 22, 2020. It is now read-only.

Xpath Exercise 3 #369

Closed
kes213 opened this issue Oct 11, 2017 · 15 comments
Closed

Xpath Exercise 3 #369

kes213 opened this issue Oct 11, 2017 · 15 comments

Comments

@kes213
Copy link
Collaborator

kes213 commented Oct 11, 2017

I'm having a lot of trouble with #3, which reads:

Write an XPath expression that returns the last paragraph in the ENTIRE Georg Forster file that contains more than one latitude record, coded as . (Hint: This builds on things we showed you in the XPath Exercise 2 homework. Note that you should only get ONE result here!)

I've tried building up from the simplest expression, but even the simple expressions are giving me errors. Here are what I've tried:

//p[geo[@select-"lat"]][2,]

//geo[@select="lat"][2,]/parent::*last()

(//p/geo[@select="lat"][2,])[last()]

(//p/geo[@select="lat" &gt 2])last()

I've probably tried at least 10 other ways to write this but I can't remember them all now. I don't know what I'm doing wrong. I just keep getting error after error. I'm trying to model my expressions after the greater than or equal to examples but it's not getting me anywhere. It keeps saying the gt needs parenthesis, but the examples on the Newtfire Xpath functions tutorial don't have parenthesis.

Can anyone help?

@ebeshero
Copy link
Owner

ebeshero commented Oct 11, 2017

@kes213 Aha! I think you're applying the repetition indicators from regular expressions to XPath. The 2, formulation you're using works in regex when you set it inside curly braces to get 2 or more of a pattern, like [A-Z]{2,}. It's a smart kind of error that shows your stripes as a coder--it comes from learning these two forms of coding back to back! :-)

Okay, we need to unpack how to get more than one of something in XPath. To do this, we need to find the paragraphs, first of all--so your expressions that start with //p are correct. And you know how to find latitude records inside with //p[geo[@select="lat"]] . Now, we need to ask XPath to determine a number of these special geo elements inside each of the <p> nodes. In a way regex was simpler for this. With XPath, we have to tell it to run a function, to get its calculator out, and don't just stop on a node. So, we need to find the <p> elements where the count of geo[@select="lat"] inside is greater than 2...Does that help?

There's a nice review of how to do this from class today posted here on our DHClass-Hub wiki. It's under the heading "Comparison Operators".

@ebeshero
Copy link
Owner

ebeshero commented Oct 11, 2017

@kes213 Of the XPath expressions you posted here, the last one looks the closest, but it's a little bit off: You're missing the function that would give a count of the geo elements you need. And when you set a comparison operator (with &gt; as you're doing) to a number greater than 2, you need to compare that "2" to a calculated number, not a node.

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

Do I need to put the &gt in parenthesis?

@ebeshero
Copy link
Owner

ebeshero commented Oct 11, 2017

@kes213 No--you'd be taking a count() of just the geo elements you're seeking, so the parentheses for the function would just wrap the part that's doing the counting. The comparison operator could be gt, &gt; or > , but we like gt here because it's for comparing exactly one thing on the left with one thing on the right. The count() function returns one thing: a number, and that number needs to be compared to the number on the right.

Does that help?

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

Well . . .

//p[count(geo[@select="lat"] gt 2)]

I tried this, and I still got an error. I just don't understand how to write the gt into the expression so that it works. I looked at the Intro to Xpath functions document on the Wiki and I still don't get it.

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

I'll play around with it some more.

@flowerbee1234
Copy link
Collaborator

Trust me I'm having so much trouble too. Everything on this assignment I was fine with--except this.

@ebeshero
Copy link
Owner

@kes213 Ahh! You're very close! You're just having trouble positioning the parentheses.

Look at the example I posted on the wiki from earlier today--and notice how the count() function wraps just the thing it's trying to count...

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

(//p[count(geo[@select="lat"]) gt 2])/last()

This is the closest I've gotten, and it's still giving me 12 results.

@ebeshero
Copy link
Owner

@kes213 @flowerbee1234 Here's that example I used in the wiki: Look at it closely:

//p[count(descendant::persName) gt 5]

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

That's the example I looked at to get my most recent expression, but it still didn't give me the single result I need.

@ebeshero
Copy link
Owner

@kes213 Yes--now you've got the count() set properly in your predicate, but the position of last() is the thing to figure out.

@flowerbee1234
Copy link
Collaborator

I put my last at the beginning. Still doesn't work

@ebeshero
Copy link
Owner

ebeshero commented Oct 11, 2017

@kes213 @flowerbee1234 Remember how you could find the very first instance of any XPath expression by walking the whole tree first and then positioning the [1] after it? Like this:

(//p[geo])[1]

Okay--that's a simpler XPath, but it's similar to what you do here. [1] is a position predicate, that says get the first in series. The last() function is what we use because we literally do not know what number of result we want. We just want the very last, whatever it is...Notice it's got to go in a predicate because it's a filter.

@kes213
Copy link
Collaborator Author

kes213 commented Oct 11, 2017

I think I figured it out. I'll put whatever I have on my text file.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants