summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2011-11-03 22:17:42 +0100
committerStefan Behnel <stefan_ml@behnel.de>2011-11-03 22:17:42 +0100
commit5fc9eac1edea42ec46422c6c7b017ee11c4a9531 (patch)
treee674719a25664310dc5a5e6c40ce9093f0fcfb6f
parentba9b186dfd3650855263514ecfff7feaa0745200 (diff)
downloadpython-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.txt16
-rw-r--r--src/lxml/cssselect.py2
-rw-r--r--src/lxml/tests/test_css.txt6
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):
...