The answer is in lxml-lpt.lua, where built-in expressions are defined. You need a good knowledge of LPEG that i miss. Some built-in expressions get the current element as first argument, like count() or child() (lines 1300-1307 of lxml-lpt.lua): expressions.child = function(e,pattern) return applylpath(e,pattern) -- todo: cache end expressions.count = function(e,pattern) -- what if pattern == empty or nil local collected = applylpath(e,pattern) -- todo: cache return pattern and (collected and #collected) or 0 end Some other expressions use a template that passes the "list", "ll", "l" and "order" arguments you find cited in the XML manual ยง4.1 "Path expressions - Expressions and filters". These are the lines 738-743 in lxml-lpt.lua: local template_e = [[ local expr = xml.expressions return function(list,ll,l,order) return %s end ]] That template is used by the function that registers a new expression (lines 807-812 in lxml-lpt.lua): local function register_expression(expression) local converted = lpegmatch(converter,expression) local runner = load(format(template_e,converted)) runner = (runner and runner()) or function() errorrunner_e(expression,converted) end return { kind = "expression", expression = expression, converted = converted, evaluator = runner } end Anyway i could not find a way to define an expression with a function like this: xml.expressions.myexpr( ... ) that gets access to those arguments. The only arguments it gets are the ones you specify in your LPATH expressions; AFAIK they are attributes values -- with the @attr syntax -- and strings. Best wishes, Massi