8 ms·
XPath post 1.0 got ridiculous, like many things do. What started with a simple, elegant language morphed into one with a http client, filesystem methods, json s
by orf 6y ago
XPath post 1.0 got ridiculous, like many things do. What started with a simple, elegant language morphed into one with a http client, filesystem methods, json support, functions, loops, extensions and the ability to read environment variables.
I wrote a post about it a while back[1] (I regret some of the wording used there) and maintain a tool[2] that can exploit XPath injection issues. I'd recommend sticking with 1 or maybe 2, and pretending 3.x doesn't exist.
1. https://tomforb.es/xcat-1.0-released-or-xpath-injection-issues-are-severely-underrated/ https://tomforb.es/xcat-1.0-released-or-xpath-injection-issu...
2. https://github.com/orf/xcat https://github.com/orf/xcat
- layoutIfNeeded 6y agoI've read your article... Holy shit. They took a simple, sed-like tool and turned it into an abomination.
- the-dude 6y agoIt ain't done before it can receive e-mail.
- hyperpallium2 6y agoEvery program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can.
- MaxBarraclough 6y agoI was going to suggest Vim as a counterexample, but sure enough https://github.com/soywod/iris.vim https://github.com/soywod/iris.vim
- tingol 6y agoThat's a community based plugin, Vim is still focused on text editing and not much else.
- marcosdumay 6y agoMost of the functionality on the editors like vim and emacs comes from community based plugins. People would mostly not use them if there were no such expansions.
- barumi 6y agoThis baseless assertion is simply wrong. Plugins are nice to have, but the bulk of their use is to customize default installs.
- oefrha 6y agoIt can receive email. See my follow-up here with a working implementation: https://github.com/clopen/xpath-receive-email https://github.com/clopen/xpath-receive-email https://news.ycombinator.com/item?id=24960548 https://news.ycombinator.com/item?id=24960548
- 0df8dkdf 6y agoHahah, that just really got carried away. Ok, any idea if there is replacement? I found version 1 useful for scrapping web sites. Or should I just stick with 1.0 ?
- riku_iki 6y agoCurious what is the problem with this? You can still use your small sed-like subset of language in your project?
- taway611 6y ago>>> They took a simple, sed-like tool and turned it into an abomination. > Curious what is the problem with this? Product Managers.
- masklinn 6y agoI largely agree. XPath 2.0 started the downwards trajectory and XPath 3 made it worse. The things XPath 2.0 and later do improve on XPath 1.0 is the "standard library", most of exslt got standardised in 2.0, and new useful functions got added in later revisions (e.g. contains-token from 3.1 is XPath finally adding the ~= operator from CSS). Here's the deal though: it should be possible to add most functions without updating the rest of the engine (indeed the majority were originally developed for 1.0). I think some of the functions are designed to work with and around types, which would not be useful in 1.0.
- benibela 6y agoThere are other useful things besides functions Sequences for example. In XPath 1 the query returns a set, so the output is always in document order. When the document reorders things, the query output changes, and you can never get the original output. In a sequence, the query can output anything in any order
- ziml77 6y agoHoly crap. What is this atrocity that is XPath 3.0!? What was wrong with sprinkling some XPath 1.0 queries into a Python script?
- deleted 6y ago[deleted]
- Mikhail_Edoshin 6y agoXPath always was extensible, at least at the implementation level. E.g. in 'lxml' it's trivial to add XPath functions with Python. Homegrown, of course, but still possible. In addition to extension elements this is about the only way to hook XSLT into the rest of the system. How else one is supposed to read environment variables from XSLT? The only other way is to pass everything via command line as parameters. It's insecure to run untrusted XPath, but isn't it same with untrusted anything? A good solution here could be a way to sandbox such XPath, i.e. to limit which functions can be called, the same way it's done with XML where you can forbid the processor to use network or access arbitrary files on case-by-case basis.
- oefrha 6y ago> How else one is supposed to read environment variables from XSLT? Setting aside whether it’s even a good idea to allow XSLT to do that, XPath is only a subset of XSLT, so you’re just changing the subject. The “path” in XPath should be a hint at what it’s supposed to be: a query language to select nodes by path in XML documents. As opposed to an alternative of Awk, or Perl.
- Mikhail_Edoshin 6y agoI'd say XPath a way to get a nodeset or another XPath type out of something. E.g. the current date is not selected from a document. There always will be a need to get yet another thing as a nodeset, e.g. list a directory. Or, for boolean expressions, there will always be a need to test yet another thing, such as an environment variable. These things, of course, should come as extension functions rather than special syntax, but then there will be a need to provide a small standard library of such functions :) So yes, I believe it's useful if we're going to use XPath in a trusted environment, e.g. as a typical command-line tool. You won't deny Bash or Python this and other powerful abilities, will you? But of course it would be very unwise to run an untrusted Bash script.
- tannhaeuser 6y agoXPath/XSLT 2+ also have only a single implementation (by the spec author) so don't meet W3C's requirement of two interoperating implementations. Basically, XSLT ceased to be a "standard" whereas XSLT 1.0 had excellent portability across libxslt, Saxon, Xalan, and MS' xslt.exe. Edit: there is/was a token implementation for XSLT 2.0 called Gestalt
- orf 6y agoSaxon supports all xpath versions though? It also bundles some very dangerous functions, some of which xcat can take advantage of.
- now 6y agoIt also worth noting that the specification’s author also built his company on this single implementation.
- zmix 6y ago> XPath/XSLT 2+ also have only a single implementation As far as XPath goes, that's wrong: 1. Saxon (the one you talk about) 2. BaseX (an XQuery 3.1 processor) 3. Xidel (implements many XQuery 3.1 features) 4. eXistdb 5. fonto-xpath (NodeJS) 6. frameless.io (JS, also XSL) And these are the ones, which face the public internet. I think, Microsoft has an 2.x implementation, I am pretty sure, IBM and Oracle do so, as well. Now, as for XSL-T, you are right: the easily available implementations are Saxon, but, as it seems, also frameless.io (which I just found out about a few minutes ago, so I may be wrong). But again, I guess, that big enterprise has their own solutions bundled.
- AtlasBarfed 6y agoWith the rise of numerous hierarchical document formats (JSON, YAML, TOML, properties files), what XPath REALLY should have evolved into was a more format-flexible path language with format-specific extensions as needed.
- masklinn 6y ago> what XPath REALLY should have evolved into was a more format-flexible path language with format-specific extensions as needed. You can probably already do that just fine: ignore attribute nodes, and e.g. {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }} /menu/popup/menuitem/*[last()]/preceding-sibling::*[1]/value selects "Open". Something along those lines. Maybe relax nodetypes so they can be pluggable per-language, but I'm not sure that's even useful or necessary.
- nunez 6y agoDamn. XPath went off the rails after v2. Though, to be fair, so did JavaScript, and look where that is today!
- forgotmypw17 6y agoA bloated abomination?
- spdionis 6y agoBut does it send email?
- ssdspoimdsjvv 6y agoXPath 3 was conceived with support for XSLT and XQuery in mind - where reading environment variables and text files are most definitely very useful features. This is indeed not something you want in a browser, but that ship had already sailed by then.
- zmix 6y agoI don't know what XPath 3.1 implementation you use, but the two major implementations, I have at hand, SaxonEE and BaseX, both do not understand your code. You write: for-each(normalize-unicode(upper-case(json-doc('x.json'))) => tokenize("\s+"), function($a) { let $a := $a * 10 load-xquery-module('abc'):some-func( function-lookup($a, 1)(array:map($a, function($b) { let $c := unparsed-text-lines($b) trace($c) if ($c) { return xml-to-json($b) } else { error('This is an error') } })) } ) 1. fn:json-doc(), by default and typically, returns either an XPath map or array datatype. Therefore fn:tokenize() can not be used with it. Just as fn:normalize-unicode() and fn:upper-case() can not (both take a string as input) The error is: [FOTY0013] Items of type map(*) cannot be atomized. 2. in your anonymous function 'function($a) {...' you use a 'let' expression without 'return'. This is illegal. 3. As is the use of a colon ':' after fn:load-xquery-module(). The colon seperates prefixes from namespaces. Did you mean the question-mark '?'? That would make sense, since fn:load-xquery-module() returns a map. But then 'some-func(...' would not work out, since the returned map has two keys: "variables" and "functions" and 'some-func()' would be referenced in another map, which is the value of the 'functions' key. 4. Calling fn:function-lookup() (as the parameter to some-func()) with a value, that must be a string ($a), which you then multiply with an integer (10)) will already have errored out (multiply string with integer is not possible), but even if this would be possible, the next error would arise since the first parameter to this function must be an xs:QName type, which a number (or string), clearly, is not. 5. The function, you look up in the external module takes an array:map() function as first parameter. Such a function does not exist in the XPath 3.1 standard (see https://maxtoroq.github.io/xpath-ref https://maxtoroq.github.io/xpath-ref). You may have studied a version of the specification, which was written, before the array functions have been finalized, which was in 2017. That could mean, that what you wanted to express, would now be array:fold-left(), which is how a map() function is being called in XPath. However, that function takes three parameters. 6. Again, this is not valid XPath grammar: let $c := unparsed-text-lines($b) trace($c) if ($c) { return xml-to-json($b) } else { error('This is an error') } It would need to be: let $c := unparsed-text-lines($b) return ( trace($c) , if ($c) then xml-to-json($b) else error('This is an error') ) Also, $c can not evaluate to a boolean ([FORG0006] Effective boolean value not defined for xs:string+), since it is a sequence of strings. Of course, such things could be implementation dependent... I don't want to go any further, since I can not totally recapitulate, what your code is supposed to do. It may be some 'blackhattish' dark magic, that fucks up some engines, but the engines I use do not even go through with compilation, due to the invalid XPath code. As is, your code does not make much sense. At least, if we talk about XPath 3.1. Your bashing of XPath 3.1 (and also 2.1) makes no sense either, since you seem to use a completely non-standard processor, with a different syntax and functions, that behave very differently from XPath 3.1, or, even worse, did not understand the language. Many of the changes to XPath, starting with version 2.1, stem from the fact, that XPath became a subset to XQuery, a fully functional and declarative programming language, that satisfies the need, to query XML documents as they would be databases. This was done in order to satisfy the needs of non-programmers, like in the digital humanities, the publishing industry, etc. XQuery 3.1, as a superset of XPath 3.1, is a language made in heaven! Nowhere is it that simple, to work with (X)HTML, JSON and XML documents as here! A fully functional, declarative language, that has templating (think handlebars, moustache) built in as an integral part of the language, where you can just intermix you XML code with program code, with easy error tracing (stateless!), quick "to production" development cycles and a painless approach to anything XML! XML is one of the most misunderstood technologies in our industry and the only solid document technology, I know of. Sadly, also based on this misunderstanding, a whole generation of developers has evolved, which listened to those, who jumped the hypetrain of XML, just to realize, that a document format may not be the best tool for the job (RPC, configuration files, etc.). And instead of admitting to themselves, that they were wrong, they accuse the technology, they abused, teaching the kids to make their lifes more difficult. And these kids now are in charge of browser development, etc. And adding to that, your lightheaded comments do not really help the issue.