Skip to content

Don't match a language prefix that is not a sublanguage in lang() - #373

Merged
kou merged 1 commit into
ruby:masterfrom
youdie006:lang-sublanguage
Sep 28, 2026
Merged

kou merged 1 commit into
ruby:masterfrom
youdie006:lang-sublanguage

Conversation

@youdie006

@youdie006 youdie006 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

XPath 1.0 lang() is true when xml:lang equals the argument or is a sublanguage of it (the argument followed by -), ignoring case. compare_language only checks for a prefix, so lang('en') also matches xml:lang="eng":

query master this PR libxml2
//p[lang('en')] over en, eng, EN-us, e en, eng, EN-us en, EN-us en, EN-us
//p[lang('e')] all four e e
//p[lang('en-US')] EN-us EN-us EN-us

https://www.w3.org/TR/xpath-10/#function-lang

The lang function returns true or false depending on whether the language of the context node as specified by xml:lang attributes is the same as or is a sublanguage of the language specified by the argument string. The language of the context node is determined by the value of the xml:lang attribute on the context node, or, if the context node has no xml:lang attribute, by the value of the xml:lang attribute on the nearest ancestor of the context node that has an xml:lang attribute. If there is no such attribute, then lang returns false. If there is such an attribute, then lang returns true if the attribute value is equal to the argument ignoring case, or if there is some suffix starting with - such that the attribute value is equal to the argument ignoring that suffix of the attribute value and ignoring case. For example, lang("en") would return true if the context node is any of these five elements:

<para xml:lang="en"/>
<div xml:lang="en"><para/></div>
<para xml:lang="EN"/>
<para xml:lang="en-us"/>

The new test sits next to test_lang; it fails on master and passes here. ruby -Ilib test/run.rb passes on Ruby 3.4 (also with --enable-frozen-string-literal), and the lang tests pass on 2.7.

Written with AI assistance (Claude); I have reviewed the change.

XPath 1.0 lang() is true when xml:lang equals the argument or is a
sublanguage of it, i.e. the argument followed by '-'. compare_language
only checked for a prefix, so lang('en') also matched xml:lang="eng".
Copilot AI lite review requested due to automatic review settings September 28, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@kou
kou merged commit 75f7337 into ruby:master Sep 28, 2026
67 of 71 checks passed
@kou

kou commented Sep 28, 2026

Copy link
Copy Markdown
Member

Good catch.

I've added the lang() part of XPath 1.0 specification to the PR description and merged this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants