diff --git a/cssselect/xpath.py b/cssselect/xpath.py index 57b9884..377fc28 100644 --- a/cssselect/xpath.py +++ b/cssselect/xpath.py @@ -420,7 +420,7 @@ def xpath_attrib(self, selector: Attrib) -> XPathExpr: getattr(self, f"xpath_attrib_{operator}"), ) if self.lower_case_attribute_names: - name = selector.attrib.lower() + name = ascii_lower(selector.attrib) else: name = selector.attrib if selector.namespace == "*": @@ -470,7 +470,7 @@ def xpath_element(self, selector: Element) -> XPathExpr: else: safe = bool(is_safe_name(element)) if self.lower_case_element_names: - element = element.lower() + element = ascii_lower(element) if selector.namespace == "*": # Namespace wildcard, e.g. "*|div": any namespace, # including none. XPath 1.0 has no "*:name" name test diff --git a/tests/test_cssselect.py b/tests/test_cssselect.py index d5d9ec7..4a98eee 100644 --- a/tests/test_cssselect.py +++ b/tests/test_cssselect.py @@ -1361,6 +1361,31 @@ def argument_types(css: str) -> list[str]: css = f"::pseudo_element({argument_string})" assert argument_types(css) == argument_list + def test_html_non_ascii_element_names(self) -> None: + xpath = HTMLTranslator().css_to_xpath + assert xpath("x-Ä") == "descendant-or-self::*[name() = 'x-Ä']" + assert xpath("X-Ä") == "descendant-or-self::*[name() = 'x-Ä']" + assert xpath("*|X-Ä") == "descendant-or-self::*[local-name() = 'x-Ä']" + assert xpath("X-ä") == "descendant-or-self::*[name() = 'x-ä']" + + def test_html_non_ascii_attribute_names(self) -> None: + xpath = HTMLTranslator().css_to_xpath + assert ( + xpath("[DATA-Ä]") + == "descendant-or-self::*[attribute::*[name() = 'data-Ä']]" + ) + assert ( + xpath('[DATA-Ä="yes"]') + == "descendant-or-self::*[attribute::*[name() = 'data-Ä'] = 'yes']" + ) + assert xpath("[*|DATA-Ä]") == ( + "descendant-or-self::*[attribute::*[local-name() = 'data-Ä']]" + ) + assert ( + xpath('[DATA-ä="yes"]') + == "descendant-or-self::*[attribute::*[name() = 'data-ä'] = 'yes']" + ) + def test_select(self) -> None: document = etree.fromstring(HTML_IDS) sort_key = {el: count for count, el in enumerate(document.iter())}.__getitem__