diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2011-11-03 22:17:42 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2011-11-03 22:17:42 +0100 |
commit | 5fc9eac1edea42ec46422c6c7b017ee11c4a9531 (patch) | |
tree | e674719a25664310dc5a5e6c40ce9093f0fcfb6f | |
parent | ba9b186dfd3650855263514ecfff7feaa0745200 (diff) | |
download | python-lxml-5fc9eac1edea42ec46422c6c7b017ee11c4a9531.tar.gz |
another fix for the 'descendant' problem in cssselect to undo a serious performance regression in 2.3.1
--HG--
extra : rebase_source : 2c4c89423870a16cc9aedc19532032d2a10bae5e
-rw-r--r-- | CHANGES.txt | 16 | ||||
-rw-r--r-- | src/lxml/cssselect.py | 2 | ||||
-rw-r--r-- | src/lxml/tests/test_css.txt | 6 |
3 files changed, 16 insertions, 8 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 195affbc..89b6c307 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -20,6 +20,13 @@ Features added Bugs fixed ---------- +* Fixed the "descendant" bug in cssselect a second time (after a first + fix in lxml 2.3.1). The previous change resulted in a serious + performance regression for the XPath based evaluation of the + translated expression. Note that this breaks the usage of some of + the generated XPath expressions as XSLT location paths that + previously worked in 2.3.1. + Other changes -------------- @@ -69,10 +76,11 @@ Bugs fixed * Assertion error in lxml.html.cleaner when discarding top-level elements. * In lxml.cssselect, use the xpath 'A//B' (short for - 'A/descendant-or-self::node()/B') instead of 'A/descendant::B' for the css - descendant selector ('A B'). This makes a few edge cases to be consistent - with the selector behavior in WebKit and Firefox, and makes more css - expressions valid location paths (for use in xsl:template match). + 'A/descendant-or-self::node()/B') instead of 'A/descendant::B' for + the css descendant selector ('A B'). This makes a few edge cases + like ``"div *:last-child"`` consistent with the selector behavior in + WebKit and Firefox, and makes more css expressions valid location + paths (for use in xsl:template match). * In lxml.html, non-selected ``<option>`` tags no longer show up in the collected form values. diff --git a/src/lxml/cssselect.py b/src/lxml/cssselect.py index cf94f7a1..8fd7faf3 100644 --- a/src/lxml/cssselect.py +++ b/src/lxml/cssselect.py @@ -494,7 +494,7 @@ class CombinedSelector(object): def _xpath_descendant(self, xpath, sub): # when sub is a descendant in any way of xpath - xpath.join('//', sub.xpath()) + xpath.join('/descendant-or-self::*/', sub.xpath()) return xpath def _xpath_child(self, xpath, sub): diff --git a/src/lxml/tests/test_css.txt b/src/lxml/tests/test_css.txt index 8aafb769..a2168c20 100644 --- a/src/lxml/tests/test_css.txt +++ b/src/lxml/tests/test_css.txt @@ -95,7 +95,7 @@ Now of translation: >>> xpath('E:nth-last-of-type(1)') */e[position() = last() - 1] >>> xpath('div E:nth-last-of-type(1) .aclass') - div//e[position() = last() - 1]//*[contains(concat(' ', normalize-space(@class), ' '), ' aclass ')] + div/descendant-or-self::*/e[position() = last() - 1]/descendant-or-self::*/*[contains(concat(' ', normalize-space(@class), ' '), ' aclass ')] >>> xpath('E:first-child') */*[name() = 'e' and (position() = 1)] >>> xpath('E:last-child') @@ -119,7 +119,7 @@ Now of translation: >>> xpath('E:not(:contains("foo"))') e[not(contains(css:lower-case(string(.)), 'foo'))] >>> xpath('E F') - e//f + e/descendant-or-self::*/f >>> xpath('E > F') e/f >>> xpath('E + F') @@ -127,7 +127,7 @@ Now of translation: >>> xpath('E ~ F') e/following-sibling::f >>> xpath('div#container p') - div[@id = 'container']//p + div[@id = 'container']/descendant-or-self::*/p >>> xpath('p *:only-of-type') Traceback (most recent call last): ... |