From 23b4cc909fba6cb61e9387f7ed5e7716f3ef183b Mon Sep 17 00:00:00 2001 From: Laurent Bachelier Date: Thu, 9 Oct 2014 16:02:43 +0200 Subject: [PATCH] Add has-class xpath function Taken from https://gist.github.com/shirk3y/458224083ce5464627bc --- weboob/browser/pages.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/weboob/browser/pages.py b/weboob/browser/pages.py index 4cf0436d..b0db8b16 100644 --- a/weboob/browser/pages.py +++ b/weboob/browser/pages.py @@ -391,6 +391,36 @@ class HTMLPage(Page): """ ns['lower-case'] = lambda context, args: ' '.join([s.lower() for s in args]) + def has_class(context, *classes): + """ + This lxml extension allows to select by CSS class more easily + + >>> ns = html.etree.FunctionNamespace(None) + >>> ns['has-class'] = has_class + >>> root = html.etree.fromstring(''' + ... + ... I + ... LOVE + ... CSS + ... + ... ''') + + >>> len(root.xpath('//b[has-class("text")]')) + 3 + >>> len(root.xpath('//b[has-class("one")]')) + 1 + >>> len(root.xpath('//b[has-class("text", "first")]')) + 1 + >>> len(root.xpath('//b[not(has-class("first"))]')) + 2 + >>> len(root.xpath('//b[has-class("not-exists")]')) + 0 + """ + expressions = ' and '.join(["contains(concat(' ', normalize-space(@class), ' '), ' {} ')".format(c) for c in classes]) + xpath = 'self::*[@class and {}]'.format(expressions) + return bool(context.context_node.xpath(xpath)) + ns['has-class'] = has_class + def build_doc(self, encoding=None): """ Method to build the lxml document from response and given encoding.