eaiovnaovbqoebvqoeavibavo 3 ǁaWa@sdZddlZddlZddlmZmZmZejddkr@eZ e Z ne Z e Z dddZ GdddeeZGd d d eZejd jZejd jZejd jZGdddeZGdddeZdS)a cssselect.xpath =============== Translation of parsed CSS selectors to XPath expressions. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. N)parse parse_series SelectorErrorcCs|jddjd}t|||S)Nasciireplace)encodedecodegetattr)objnamedefaultr/usr/lib/python3.6/xpath.py_unicode_safe_getattrsrc@seZdZdZdS)ExpressionErrorz3Unknown or unsupported selector (eg. pseudo-class).N)__name__ __module__ __qualname____doc__rrrrr#src@sFeZdZdddZddZdd Zd d Zd d ZddZddZ dS) XPathExpr*FcCs||_||_||_dS)N)pathelement condition)selfrrrZ star_prefixrrr__init__+szXPathExpr.__init__cCs,t|jt|j}|jr(|d|j7}|S)Nz[%s])_unicoderrr)rrrrr__str__0szXPathExpr.__str__cCsd|jj|fS)Nz%s[%s]) __class__r)rrrr__repr__6szXPathExpr.__repr__cCs"|jrd|j|f|_n||_|S)Nz %s and (%s))r)rrrrr add_condition9szXPathExpr.add_conditioncCs.|jdkrdS|jdtj|jd|_dS)Nrz name() = %s)rr"GenericTranslator xpath_literal)rrrr add_name_test@s  zXPathExpr.add_name_testcCs|jd7_dS)ze Append '*/' to the path to keep the context constrained to a single parent. z*/N)r)rrrradd_star_prefixHszXPathExpr.add_star_prefixcCs:t||}|jdkr ||j7}||_|j|_|j|_|S)Nz*/)rrrr)rZcombinerotherrrrrjoinOs   zXPathExpr.joinN)rrrF) rrrrrr!r"r%r&r(rrrrr)s rz('+)z^[a-zA-Z_][a-zA-Z0-9_.-]*$z^[^ \t\r\n\f]+$c @seZdZdZdddddZddd d d d d ddZdZdZdZdZ dZ e Z dfddZ dgddZddZeddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1Zd2d3Zd4d5Zdhd7d8Zd9d:Z d;d<Z!d=d>Z"d?d@Z#dAdBZ$dCdDZ%dEdFZ&dGdHZ'dIdJZ(dKdLZ)dMdNZ*dOdPZ+dQdRZ,dSdTZ-e-Z.e-Z/e-Z0e-Z1e-Z2e-Z3e-Z4e-Z5e-Z6dUdVZ7dWdXZ8dYdZZ9d[d\Z:d]d^Z;d_d`ZdeS)ir#z Translator for "generic" XML documents. Everything is case-sensitive, no assumption is made on the meaning of element names and attribute names. Z descendantZchildZdirect_adjacentZindirect_adjacent) >+~existsZequalsZincludesZ dashmatchZ prefixmatchZ suffixmatchZsubstringmatchZ different)r-=z~=z|=z^=z$=z*=z!=idzxml:langFdescendant-or-self::csdjfddt|DS)uTranslate a *group of selectors* to XPath. Pseudo-elements are not supported here since XPath only knows about "real" elements. :param css: A *group of selectors* as an Unicode string. :param prefix: This string is prepended to the XPath expression for each selector. The default makes selectors scoped to the context node’s subtree. :raises: :class:`SelectorSyntaxError` on invalid selectors, :class:`ExpressionError` on unknown/unsupported selectors, including pseudo-elements. :returns: The equivalent XPath 1.0 expression as an Unicode string. z | c3s|]}j|ddVqdS)T)translate_pseudo_elementsN)selector_to_xpath).0selector)prefixrrr sz1GenericTranslator.css_to_xpath..)r(r)rZcssr5r)r5rr css_to_xpathszGenericTranslator.css_to_xpathcCs`t|dd}|std|f|j|}t||js8t|rP|jrP|j||j}|pVdt|S)u4Translate a parsed selector to XPath. :param selector: A parsed :class:`Selector` object. :param prefix: This string is prepended to the resulting XPath expression. The default makes selectors scoped to the context node’s subtree. :param translate_pseudo_elements: Unless this is set to ``True`` (as :meth:`css_to_xpath` does), the :attr:`~Selector.pseudo_element` attribute of the selector is ignored. It is the caller's responsibility to reject selectors with pseudo-elements, or to account for them somehow. :raises: :class:`ExpressionError` on unknown/unsupported selectors. :returns: The equivalent XPath 1.0 expression as an Unicode string. Z parsed_treeNz"Expected a parsed selector, got %rr) r TypeErrorxpath isinstance xpathexpr_clsAssertionErrorpseudo_elementxpath_pseudo_elementr)rr4r5r1Ztreer9rrrr2s   z#GenericTranslator.selector_to_xpathcCs tddS)zTranslate a pseudo-element. Defaults to not supporting pseudo-elements at all, but can be overridden by sub-classes. z"Pseudo-elements are not supported.N)r)rr9r=rrrr>sz&GenericTranslator.xpath_pseudo_elementcCsLt|}d|krd|}n.d|kr,d|}nddjddt|D}|S) N'z'%s'"z"%s"z concat(%s),cSs$g|]}|rd|krdpd|qS)r?z"%s"z'%s'r)r3partrrr sz3GenericTranslator.xpath_literal..)rr(split_at_single_quotes)srrrr$s  zGenericTranslator.xpath_literalcCs:t|j}t|d|jd}|dkr2td|||S)z%Translate any parsed selector object.zxpath_%sNz%s is not supported.)typerr lowerr)rZparsed_selectorZ type_namemethodrrrr9s   zGenericTranslator.xpathcCs4|j|j}t|d|}||j|j|j|jS)zTranslate a combined selector.zxpath_%s_combinator)combinator_mapping combinatorr r9r4 subselector)rZcombinedrJrHrrrxpath_combinedselectors  z(GenericTranslator.xpath_combinedselectorcCsD|j|j}|j|j}|j|jr6|jd|jS|jdSdS)Nznot(%s)0)r9r4rKr%rr")rZnegationr9Z sub_xpathrrrxpath_negation s   z GenericTranslator.xpath_negationcCsBd|jjdd}t||d}|s0td|j||j|j|S)z$Translate a functional pseudo-class.zxpath_%s_function-_Nz!The pseudo-class :%s() is unknown)r rrrr9r4)rfunctionrHrrrxpath_functions   z GenericTranslator.xpath_functioncCs@d|jjdd}t||d}|s0td|j||j|jS)zTranslate a pseudo-class.zxpath_%s_pseudorOrPNzThe pseudo-class :%s is unknown)Zidentrrrr9r4)rZpseudorHrrr xpath_pseudos   zGenericTranslator.xpath_pseudocCs|j|j}t|d|}|jr,|jj}n|j}t|}|jr\d|j|f}|oZt|j}|rjd|}nd|j|}|j r|j j}n|j }||j |j ||S)z Translate an attribute selector.zxpath_attrib_%sz%s:%s@zattribute::*[name() = %s]) attribute_operator_mappingoperatorr lower_case_attribute_namesattribrG is_safe_name namespacer$lower_case_attribute_valuesvaluer9r4)rr4rVrHr saferXr\rrr xpath_attrib's     zGenericTranslator.xpath_attribcCs|j|j}|j|d|jS)zTranslate a class selector.z@class)r9r4xpath_attrib_includes class_name)rZclass_selectorr9rrr xpath_class=s zGenericTranslator.xpath_classcCs|j|j}|j|d|jS)zTranslate an ID selector.z@id)r9r4xpath_attrib_equalsr/)rZ id_selectorr9rrr xpath_hashDs zGenericTranslator.xpath_hashcCsh|j}|sd}d}nt|}|jr*|j}|jrLd|j|f}|oJt|j}|j|d}|sd|j|S)z'Translate a type or universal selector.rTz%s:%s)r)rrYlower_case_element_namesrGrZr;r%)rr4rr]r9rrr xpath_elementIs zGenericTranslator.xpath_elementcCs |jd|S)z;right is a child, grand-child or further descendant of leftz/descendant-or-self::*/)r()rleftrightrrrxpath_descendant_combinator`sz-GenericTranslator.xpath_descendant_combinatorcCs |jd|S)z#right is an immediate child of left/)r()rrfrgrrrxpath_child_combinatordsz(GenericTranslator.xpath_child_combinatorcCs|jd|}|j|jdS)z)right is a sibling immediately after leftz/following-sibling::zposition() = 1)r(r%r")rrfrgr9rrr xpath_direct_adjacent_combinatorhs z2GenericTranslator.xpath_direct_adjacent_combinatorcCs |jd|S)z1right is a sibling after left, immediately or notz/following-sibling::)r()rrfrgrrr"xpath_indirect_adjacent_combinatornsz4GenericTranslator.xpath_indirect_adjacent_combinatorTc Csyt|j\}}Wn"tk r4td|jYnX|rB|j|j|dkrl|r^d|}|jd|S|r|| }| }|dkrt| }n d| }|dkrd||fg}ng}|dkr|jd|n|dkr|r|jd |d j |}|r|j||S) NzInvalid series: '%r'rz last() - %szposition() = %sz+%sz(position() %s) mod %s = 0zposition() >= %szposition() < (last() %s)z and ) r arguments ValueErrorrr%r&r"strappendr() rr9rQlastr%abZb_negexprrrrxpath_nth_child_functionus8     z*GenericTranslator.xpath_nth_child_functioncCs|j||ddS)NT)rr)rv)rr9rQrrrxpath_nth_last_child_functionsz/GenericTranslator.xpath_nth_last_child_functioncCs"|jdkrtd|j||ddS)Nrz"*:nth-of-type() is not implementedF)r%)rrrv)rr9rQrrrxpath_nth_of_type_functions  z,GenericTranslator.xpath_nth_of_type_functioncCs$|jdkrtd|j||dddS)Nrz"*:nth-of-type() is not implementedTF)rrr%)rrrv)rr9rQrrrxpath_nth_last_of_type_functions   z1GenericTranslator.xpath_nth_last_of_type_functioncCsB|jdgdgfkr"td|j|jdj}|jd|j|S)NSTRINGIDENTz9Expected a single string or ident for :contains(), got %rrzcontains(., %s))argument_typesrrnr\r"r$)rr9rQr\rrrxpath_contains_functions  z)GenericTranslator.xpath_contains_functioncCsB|jdgdgfkr"td|j|jdj}|jd|j|S)Nrzr{z5Expected a single string or ident for :lang(), got %rrzlang(%s))r|rrnr\r"r$)rr9rQr\rrrxpath_lang_functions  z%GenericTranslator.xpath_lang_functioncCs |jdS)Nznot(parent::*))r")rr9rrrxpath_root_pseudosz#GenericTranslator.xpath_root_pseudocCs|j|j|jdS)Nzposition() = 1)r&r%r")rr9rrrxpath_first_child_pseudosz*GenericTranslator.xpath_first_child_pseudocCs|j|j|jdS)Nzposition() = last())r&r%r")rr9rrrxpath_last_child_pseudosz)GenericTranslator.xpath_last_child_pseudocCs$|jdkrtd|j|jdS)Nrz"*:first-of-type is not implementedzposition() = 1)rrr&r")rr9rrrxpath_first_of_type_pseudos  z,GenericTranslator.xpath_first_of_type_pseudocCs$|jdkrtd|j|jdS)Nrz!*:last-of-type is not implementedzposition() = last())rrr&r")rr9rrrxpath_last_of_type_pseudos  z+GenericTranslator.xpath_last_of_type_pseudocCs|j|j|jdS)Nz last() = 1)r%r&r")rr9rrrxpath_only_child_pseudosz)GenericTranslator.xpath_only_child_pseudocCs|jdkrtd|jdS)Nrz!*:only-of-type is not implementedz last() = 1)rrr")rr9rrrxpath_only_of_type_pseudos z+GenericTranslator.xpath_only_of_type_pseudocCs |jdS)Nznot(*) and not(string-length()))r")rr9rrrxpath_empty_pseudosz$GenericTranslator.xpath_empty_pseudocCs |jdS)z:Common implementation for pseudo-classes that never match.rM)r")rr9rrrpseudo_never_matchessz&GenericTranslator.pseudo_never_matchescCs| s t|j||S)N)r<r")rr9r r\rrrxpath_attrib_existss  z%GenericTranslator.xpath_attrib_existscCs|jd||j|f|S)Nz%s = %s)r"r$)rr9r r\rrrrbsz%GenericTranslator.xpath_attrib_equalscCs<|r |jd|||j|fn|jd||j|f|S)Nznot(%s) or %s != %sz%s != %s)r"r$)rr9r r\rrrxpath_attrib_differents z(GenericTranslator.xpath_attrib_differentcCs:t|r,|jd|||jd|dfn |jd|S)Nz:%s and contains(concat(' ', normalize-space(%s), ' '), %s)r)rM)is_non_whitespacer"r$)rr9r r\rrrr_s  z'GenericTranslator.xpath_attrib_includesc Cs,|jd|||j|||j|df|S)Nz'%s and (%s = %s or starts-with(%s, %s))rO)r"r$)rr9r r\rrrxpath_attrib_dashmatchs  z(GenericTranslator.xpath_attrib_dashmatchcCs.|r |jd|||j|fn |jd|S)Nz%s and starts-with(%s, %s)rM)r"r$)rr9r r\rrrxpath_attrib_prefixmatch#s  z*GenericTranslator.xpath_attrib_prefixmatchcCs:|r,|jd|||t|d|j|fn |jd|S)Nz/%s and substring(%s, string-length(%s)-%s) = %srmrM)r"lenr$)rr9r r\rrrxpath_attrib_suffixmatch+s " z*GenericTranslator.xpath_attrib_suffixmatchcCs.|r |jd|||j|fn |jd|S)Nz%s and contains(%s, %s)rM)r"r$)rr9r r\rrrxpath_attrib_substringmatch5s  z-GenericTranslator.xpath_attrib_substringmatchN)r0)r0F)FT)?rrrrrIrUZ id_attributelang_attributerdrWr[rr;r7r2r> staticmethodr$r9rLrNrRrSr^rarcrerhrjrkrlrvrwrxryr}r~rrrrrrrrrxpath_link_pseudoZxpath_visited_pseudoZxpath_hover_pseudoZxpath_active_pseudoZxpath_focus_pseudoZxpath_target_pseudoxpath_enabled_pseudoxpath_disabled_pseudoxpath_checked_pseudorrbrr_rrrrrrrrr#gs        (     r#c@sFeZdZdZdZdddZddZdd Zd d Zd d Z ddZ dS)HTMLTranslatora Translator for (X)HTML documents. Has a more useful implementation of some pseudo-classes based on HTML-specific element names and attribute names, as described in the `HTML5 specification`_. It assumes no-quirks mode. The API is the same as :class:`GenericTranslator`. .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors :param xhtml: If false (the default), element names and attribute names are case-insensitive. ZlangFcCs||_|sd|_d|_dS)NT)xhtmlrdrW)rrrrrrRszHTMLTranslator.__init__cCs |jdS)Nz(@selected and name(.) = 'option') or (@checked and (name(.) = 'input' or name(.) = 'command')and (@type = 'checkbox' or @type = 'radio')))r")rr9rrrrYsz#HTMLTranslator.xpath_checked_pseudocCsP|jdgdgfkr"td|j|jdj}|jd|j|j|jdfS)Nrzr{z5Expected a single string or ident for :lang(), got %rrzancestor-or-self::*[@lang][1][starts-with(concat(translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-'), %s)]rO)r|rrnr\r"rr$rG)rr9rQr\rrrr~as  z"HTMLTranslator.xpath_lang_functioncCs |jdS)NzA@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area'))r")rr9rrrrosz HTMLTranslator.xpath_link_pseudocCs |jdS)Na ( @disabled and ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' or name(.) = 'option' ) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' ) and ancestor::fieldset[@disabled] ) )r")rr9rrrrvsz$HTMLTranslator.xpath_disabled_pseudocCs |jdS)Na' ( @href and ( name(.) = 'a' or name(.) = 'link' or name(.) = 'area' ) ) or ( ( name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' ) and not(@disabled) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'keygen' ) and not (@disabled or ancestor::fieldset[@disabled]) ) or ( name(.) = 'option' and not( @disabled or ancestor::optgroup[@disabled] ) ) )r")rr9rrrrsz#HTMLTranslator.xpath_enabled_pseudoN)F) rrrrrrrr~rrrrrrrr?s r)N)rsysreZcssselect.parserrrr version_infoZ basestringZ _basestringZunicoderrpr RuntimeErrorrobjectrcompilesplitrDmatchrYrr#rrrrr s& 1   [