diff --git a/scrapy/selector/unified.py b/scrapy/selector/unified.py index 790937af5..babb65070 100644 --- a/scrapy/selector/unified.py +++ b/scrapy/selector/unified.py @@ -57,6 +57,7 @@ class Selector(object_ref): # set:trailing "set": "http://exslt.org/sets" } + _lxml_smart_strings = False def __init__(self, response=None, text=None, type=None, namespaces=None, _root=None, _expr=None): @@ -85,7 +86,8 @@ class Selector(object_ref): return SelectorList([]) try: - result = xpathev(query, namespaces=self.namespaces) + result = xpathev(query, namespaces=self.namespaces, + smart_strings=self._lxml_smart_strings) except etree.XPathError: raise ValueError("Invalid XPath: %s" % query) diff --git a/scrapy/tests/test_selector.py b/scrapy/tests/test_selector.py index d84e4bd47..489a163a0 100644 --- a/scrapy/tests/test_selector.py +++ b/scrapy/tests/test_selector.py @@ -297,6 +297,41 @@ class SelectorTestCase(unittest.TestCase): sel.remove_namespaces() self.assertEqual(len(sel.xpath("//link/@type")), 2) + def test_smart_strings(self): + """Lxml smart strings return values""" + + class SmartStringsSelector(Selector): + _lxml_smart_strings = True + + body = """ +
+ +
+
+ +
+ """ + + response = HtmlResponse(url="http://example.com", body=body) + + # .getparent() is available for text nodes and attributes + # only when smart_strings are on + x = self.sscls(response) + li_text = x.xpath('//li/text()') + self.assertFalse(any(map(lambda e: hasattr(e._root, 'getparent'), li_text))) + div_class = x.xpath('//div/@class') + self.assertFalse(any(map(lambda e: hasattr(e._root, 'getparent'), div_class))) + + x = SmartStringsSelector(response) + li_text = x.xpath('//li/text()') + self.assertTrue(all(map(lambda e: hasattr(e._root, 'getparent'), li_text))) + div_class = x.xpath('//div/@class') + self.assertTrue(all(map(lambda e: hasattr(e._root, 'getparent'), div_class))) + class DeprecatedXpathSelectorTest(unittest.TestCase):