diff --git a/scrapy/trunk/scrapy/tests/test_xpath.py b/scrapy/trunk/scrapy/tests/test_xpath.py index 9b1efb2be..3a8e6dd78 100644 --- a/scrapy/trunk/scrapy/tests/test_xpath.py +++ b/scrapy/trunk/scrapy/tests/test_xpath.py @@ -26,7 +26,7 @@ class XPathTestCase(unittest.TestCase): xl = xpath.x('//input') self.assertEqual(2, len(xl)) for x in xl: - assert isinstance(x, XPathSelector) + assert isinstance(x, HtmlXPathSelector) self.assertEqual(xpath.x('//input').extract(), [x.extract() for x in xpath.x('//input')]) @@ -41,6 +41,26 @@ class XPathTestCase(unittest.TestCase): self.assertEqual([x.extract() for x in xpath.x("concat(//input[@name='a']/@value, //input[@name='b']/@value)")], [u'12']) + def test_selector_same_type(self): + """Test XPathSelector returning the same type in x() method""" + text = '

test

' + assert isinstance(XmlXPathSelector(text=text).x("//p")[0], + XmlXPathSelector) + assert isinstance(HtmlXPathSelector(text=text).x("//p")[0], + HtmlXPathSelector) + + def test_selector_xml_html(self): + """Test that XML and HTML XPathSelector's behave differently""" + + # some text which is parsed differently by XML and HTML flavors + text = '

Hello

' + + self.assertEqual(XmlXPathSelector(text=text).x("//div").extract(), + [u'

Hello

']) + + self.assertEqual(HtmlXPathSelector(text=text).x("//div").extract(), + [u'

Hello

']) + def test_selector_nested(self): """Nested selector tests""" body = """ diff --git a/scrapy/trunk/scrapy/xpath/selector.py b/scrapy/trunk/scrapy/xpath/selector.py index 70e007457..566ed53d5 100644 --- a/scrapy/trunk/scrapy/xpath/selector.py +++ b/scrapy/trunk/scrapy/xpath/selector.py @@ -39,10 +39,11 @@ class XPathSelector(object): if hasattr(self.xmlNode, 'xpathEval'): self.doc.xpathContext.setContextNode(self.xmlNode) xpath_result = self.doc.xpathContext.xpathEval(xpath) + cls = type(self) if hasattr(xpath_result, '__iter__'): - return XPathSelectorList([XPathSelector(node=node, parent=self, expr=xpath) for node in xpath_result]) + return XPathSelectorList([cls(node=node, parent=self, expr=xpath) for node in xpath_result]) else: - return XPathSelectorList([XPathSelector(node=xpath_result, parent=self, expr=xpath)]) + return XPathSelectorList([cls(node=xpath_result, parent=self, expr=xpath)]) else: return XPathSelectorList([]) @@ -77,7 +78,7 @@ class XPathSelector(object): self.doc.xpathContext.xpathRegisterNs(prefix, uri) def __str__(self): - return "" % (getattr(self.xmlNode, 'name'), self.expr) + return "<%s (%s) xpath=%s>" % (type(self).__name__, getattr(self.xmlNode, 'name'), self.expr) __repr__ = __str__ @@ -100,12 +101,15 @@ class XPathSelectorList(list): XPathSelector of the list""" return [x.extract() if isinstance(x, XPathSelector) else x for x in self] + class XmlXPathSelector(XPathSelector): """XPathSelector for XML content""" - def __init__(self, response=None, text=None): - XPathSelector.__init__(self, response=response, text=text, constructor=xmlDoc_from_xml) + def __init__(self, *args, **kwargs): + kwargs['constructor'] = xmlDoc_from_xml + XPathSelector.__init__(self, *args, **kwargs) class HtmlXPathSelector(XPathSelector): """XPathSelector for HTML content""" - def __init__(self, response=None, text=None): - XPathSelector.__init__(self, response=response, text=text, constructor=xmlDoc_from_html) + def __init__(self, *args, **kwargs): + kwargs['constructor'] = xmlDoc_from_html + XPathSelector.__init__(self, *args, **kwargs)