An improved ?? construct is part of the public API now. It can be used to attach predicates to node tests: xmlNode / 'foo' / ('bar' ?? 10).
or to filter result node sets like this: (xmlNode / 'foo' / 'bar') ?? 10. xmlNode / 'foo' / 'bar' ?? 10. "same because of precedence" The first is equivalent to this: 'foo/bar[10]' asXPath in: xmlNode. The others are equivalent to this: '(foo/bar)[10]' asXPath in: xmlNode. Block predicates take the context node, position, and size as optional (cull:) arguments. Multiple predicates are done by giving ?? an Array argument or chaining ?? sends like this: xmlNode / 'foo' / ('bar' ?? [:each | each includesAttribute: 'name'] ?? 1). Number predicates are faster than blocks and an initial number predicate attached to a node test (like in the first example) optimizes the node test by limiting the number of matching nodes it enumerates. > Sent: Saturday, September 03, 2016 at 11:08 AM > From: PBKResearch <pe...@pbkresearch.co.uk> > To: "'Any question about pharo is welcome'" <pharo-users@lists.pharo.org> > Subject: Re: [Pharo-users] Coding XPath as Smalltalk > > Hi Monty > > Just to say that I have obtained the Moose 6.0 image (Pharo5.0 Latest update: > #50761) and installed the XMLHTMLParser, and I seem able to reproduce the > nucleus of the results I had from my old image. Some of my old XPath strings > do not work (e.g. it did not recognise [1]), but I have worked my way round > that, and I should soon have worked out the new syntax. Thanks for your > suggestions for the variable case; I can now see the way ahead for that. > Thanks for all the help. > > @stef > > I have loaded the same version of TextLint as I had in the previous image. It > was accepted with no problems. I have tested it for the limited uses I make > of it (just the parsers, not the rules) and everything seems OK. So now I am > upgraded to Pharo 5, so far with no problems! > > Peter Kenny > > -----Original Message----- > From: Pharo-users [mailto:pharo-users-boun...@lists.pharo.org] On Behalf Of > monty > Sent: 03 September 2016 13:00 > To: pharo-users@lists.pharo.org > Subject: Re: [Pharo-users] Coding XPath as Smalltalk > > > > > Sent: Saturday, September 03, 2016 at 5:30 AM > > From: PBKResearch <pe...@pbkresearch.co.uk> > > To: "'Any question about pharo is welcome'" <pharo-users@lists.pharo.org> > > Subject: Re: [Pharo-users] Coding XPath as Smalltalk > > > > Hi Monty > > > > Many thanks. I have picked up a project that I had not worked on for a > > while, which explains why I am using an old image. I shall try the latest > > Moose image, as you suggest. My only anxiety is that I need to be able to > > use a rather ancient package called TextLint, and I do not know whether it > > will load OK in a new Pharo. If not, I shall try to update my existing > > image. > > If you'd looked at CI job, you'd see that XPath builds on Pharo 5 through 3 > (but should work back to 1.4). You can always start fresh with a clean, old > image from http://files.pharo.org/image/ or the Moose website if TextLint > doesn't work anymore. > > > With the latest XPath, will it be clear how to use the binary syntax to > > carry out node tests like the example of '//div[@id=''catlinks'']//' that I > > cited below? The case I am interested in is where the actual identifier > > ('catlinks' in this case) is a variable rather than a constant. It would be > > possible to do it in standard XPath by assembling the XPath string with a > > variable component, but it might be more convenient in the binary syntax. > > > > You could do this: > ((doc // 'div') select: [:each | (each attributeAt: 'id') = catlinks]) // > 'li' // 'text()' > > where "catlinks" is a var. Or you could use xPath:context: with an XPath var > that you dynamically bind using custom contexts: > doc > xPath: '//div[@id=$catlinks]//li//text()' > context: (XPathContext variables: {'catlinks' -> catlinks}) > > The advantage over this: > doc xPath: '//div[@id=''', catlinks, ''']//li//text()' > > is that the xPath: expression string is the same each time, so it's only > compiled once, the first time, and cached for later uses (inspect 'XPath > compiledXPathCache') instead of being compiled each time the xPath: > expression string arg changes. > > > Many thanks for your help. > > > > Peter Kenny > > > > -----Original Message----- > > From: Pharo-users [mailto:pharo-users-boun...@lists.pharo.org] On Behalf Of > > monty > > Sent: 03 September 2016 06:54 > > To: pharo-users@lists.pharo.org > > Subject: Re: [Pharo-users] Coding XPath as Smalltalk > > > > Peter, you're using an ancient version with bugs that were fixed last fall. > > The newest version has more tests and correct behavior (checked against a > > reference implementation). Just download a new Moose image and you'll get > > it, along with an up to date XMLParser. (But if you insist on upgrading in > > your old image, run "XPath initialize" after) > > > > The binary syntax (there are keyword equivalents now) officially only > > supports XPath axis selectors like #/ and #// that take node test arguments > > where the node tests can be name tests like 'name,' '*', 'prefix:*' or type > > tests like 'text()', 'comment()', 'element(name)'. > > > > Filters aren't officially supported with that syntax, but you can always > > use select: on the result. ?? was removed, but I might add it back as > > shorthand. Filters are implemented differently now. > > > > > From: PBKResearch <pe...@pbkresearch.co.uk> > > > To: pharo-users@lists.pharo.org > > > Subject: [Pharo-users] Coding XPath as Smalltalk > > > > > > Hello > > > > > > I am using XPath as a way of dissecting web pages, especially from > > > Wiktionary. Generally I get good results, but I could get useful extra > > > flexibility by using the binary Smalltalk operators to represent XPath, > > > as mentioned at the end of the class comment for XPath. However, the > > > description there is very terse, and I am having difficulty seeing how to > > > include more complex expressions, especially attribute tests. I have put > > > some of my XPath expressions through the XPath compiler and looked at the > > > output, and out of that I have found expressions which work but look very > > > clumsy. As an example, I have used the fragment: > > > > > > document xPath: '//div[@id=''catlinks'']//li//text()' > > > > > > and found that an equivalent is: > > > > > > document //'div' ?? [:node :x :y|(node attributeAt: 'id') = > > > 'catlinks']//'li'//[:n| n isStringNode]]. > > > (I had to put two dummy arguments in the three-argument block to get it > > > to work.) > > > > > > Is there a more extensive explanation of the use of these binary > > > operators? If not, could some kind person show me the most concise > > > translation of the sample XPath above, to give me a start in working out > > > more complex cases? > > > > > > Many thanks for any help. > > > > > > Peter Kenny > > > > > > > > >