Skip to content

Commit 053f266

Browse files
committed
Implement CSS immediate children
1 parent f52371a commit 053f266

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

cssselect/parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ def parse_simple_selector(stream, inside_negation=False):
400400
stream.skip_whitespace()
401401
selector_start = len(stream.used)
402402
peek = stream.peek()
403-
if peek.type == 'IDENT' or peek == ('DELIM', '*') or peek == ('DELIM', '^'):
404-
if peek.type == 'IDENT' or peek == ('DELIM', '^'):
403+
if peek.type == 'IDENT' or peek == ('DELIM', '*') or peek == ('DELIM', '<'):
404+
if peek.type == 'IDENT' or peek == ('DELIM', '<'):
405405
namespace = stream.next().value
406406
else:
407407
stream.next()

cssselect/xpath.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,6 @@ def css_to_xpath(self, css, prefix='descendant-or-self::'):
187187
The equivalent XPath 1.0 expression as an Unicode string.
188188
189189
"""
190-
# no prefix if css immediate children (example: css "^ > div" to xpath "./div")
191-
child_re = r'^[ \t\r\n\f]*\^[ \t\r\n\f]*>'
192-
if re.match(child_re, css):
193-
prefix = ''
194-
# prefix = 'child::'
195-
# css = re.sub(child_re, '', css)
196-
# print('*' * 50)
197-
# print(css)
198190
return ' | '.join(self.selector_to_xpath(selector, prefix,
199191
translate_pseudo_elements=True)
200192
for selector in parse(css))
@@ -228,7 +220,18 @@ def selector_to_xpath(self, selector, prefix='descendant-or-self::',
228220
assert isinstance(xpath, self.xpathexpr_cls) # help debug a missing 'return'
229221
if translate_pseudo_elements and selector.pseudo_element:
230222
xpath = self.xpath_pseudo_element(xpath, selector.pseudo_element)
231-
return (prefix or '') + _unicode(xpath)
223+
224+
unicode_xpath = _unicode(xpath)
225+
# CSS immediate children (CSS "<> div" to XPath "child::div" or "./div")
226+
# Works only at the start of a selector
227+
# Needed to get immediate children of a processed selector in Scrapy
228+
# product = response.css('.product')
229+
# name = product.css('<> div')
230+
child_re = r'^[ \t\r\n\f]*\<[ \t\r\n\f]*\/'
231+
if re.match(child_re, unicode_xpath):
232+
prefix = 'child::'
233+
unicode_xpath = re.sub(child_re, '', unicode_xpath)
234+
return (prefix or '') + unicode_xpath
232235

233236
def xpath_pseudo_element(self, xpath, pseudo_element):
234237
"""Translate a pseudo-element.
@@ -340,8 +343,8 @@ def xpath_element(self, selector):
340343
if not element:
341344
element = '*'
342345
safe = True
343-
if element == '^':
344-
element = '.'
346+
if element == '<':
347+
element = '<'
345348
safe = True
346349
else:
347350
safe = is_safe_name(element)

0 commit comments

Comments
 (0)