有没有更简洁的方法来实现css'An + B微语法作为xpath谓词?

Dec*_*ler 7 algorithm logic xpath predicate css-selectors

我正在为xpath 1转换器创建一个CSS选择器,而我最挣扎的一个细节就是找到An+B微语法的简洁替代品.

由于我是为xpath 1实现它并且以尽可能通用的方式实现它,因此我生成的谓词必须遵守一些约束:

  1. 我(相信我)不能使用position(),因为这取决于可能在前的谓词.

  2. 所有*-of-type伪类等价物都将由宿主语言中的外部函数生成,因为我认为没有办法根据xpath 1中前一个上下文节点的名称构建谓词.

    例如,硬编码li:first-of-type

    //li[count(preceding-sibling::li) = 0]
    
    Run Code Online (Sandbox Code Playgroud)

    很好.但动态编码*:first-of-type就像

    //*[count(preceding-sibling::*[name()=name(.)]) = 0]
    <!-- this is probably silly anyway -->
    
    Run Code Online (Sandbox Code Playgroud)

    我相信在xpath 1中是不可能的.

所以,这是我提出的"模板"谓词nth-of-type(An+B),宿主语言将填充缺少的值:

<!-- 
  $A  represents the step (A) I will insert
  $Am represents "mod $A" I will insert if $A != 0
  $B  represents the offset (B) I will insert
  $E  represents the element name I will insert
  $O  represents the operator I will insert: <= if $A is negative, else >=
-->
[count(preceding-sibling::$E) + 1 - $B $O 0 and
 (count(preceding-sibling::$E) + 1 - $B) $Am = 0]
Run Code Online (Sandbox Code Playgroud)

li:nth-of-type(2n+3) 因此会变成:

<!-- 
  $A  (step) = 2
  $Am (mod step) = mod $A = mod 2
  $B  (offset) = 3
  $E  (element name) = li
  $O  (comparison operator) = >=
-->
[count(preceding-sibling::li) + 1 - 3 >= 0 and
 (count(preceding-sibling::li) + 1 - 3) mod 2 = 0]
Run Code Online (Sandbox Code Playgroud)

li:nth-of-type(-2n+3) 因此会变成:

<!-- 
  $A  (step) = -2
  $Am (mod step) = mod $A = mod -2
  $B  (offset) = 3
  $E  (element name) = li
  $O  (comparison operator) = <=
-->
[count(preceding-sibling::li) + 1 - 3 <= 0 and
 (count(preceding-sibling::li) + 1 - 3) mod -2 = 0]
Run Code Online (Sandbox Code Playgroud)

li:nth-of-type(3) 因此会变成:

<!-- 
  $A  (step) = 0
  $Am (mod step) = absent
  $B  (offset) = 3
  $E  (element name) = li
  $O  (comparison operator) = >=

  first line seems redundant now
-->
[count(preceding-sibling::li) + 1 - 3 >= 0 and
 (count(preceding-sibling::li) + 1 - 3) = 0]
Run Code Online (Sandbox Code Playgroud)

...等等.

如你所见,它有点笨拙.我最好创建一个很好的紧凑的单线性谓词,没有看似冗余的位,并且对变量替换的需求最少(特别是比较运算符和与步骤相关的mod计算).

有没有更简洁的方法来结合An+B我上面显示的(步进和偏移)功能?