/**
* undocumented function
*
* @param XPathExpr $xpath
* @param mixed $expr
* @param Boolean $last
* @param Boolean $addNameTest
* @return XPathExpr
*/
protected function _xpath_nth_child($xpath, $expr, $last = false, $addNameTest = true)
{
list($a, $b) = $this->parseSeries($expr);
if (!$a && !$b && !$last) {
// a=0 means nothing is returned...
$xpath->addCondition('false() and position() = 0');
return $xpath;
}
if ($addNameTest) {
$xpath->addNameTest();
}
$xpath->addStarPrefix();
if ($a == 0) {
if ($last) {
$b = sprintf('last() - %s', $b);
}
$xpath->addCondition(sprintf('position() = %s', $b));
return $xpath;
}
if ($last) {
// FIXME: I'm not sure if this is right
$a = -$a;
$b = -$b;
}
if ($b > 0) {
$bNeg = -$b;
} else {
$bNeg = sprintf('+%s', -$b);
}
if ($a != 1) {
$expr = array(sprintf('(position() %s) mod %s = 0', $bNeg, $a));
} else {
$expr = array();
}
if ($b >= 0) {
$expr[] = sprintf('position() >= %s', $b);
} elseif ($b < 0 && $last) {
$expr[] = sprintf('position() < (last() %s)', $b);
}
$expr = implode($expr, ' and ');
if ($expr) {
$xpath->addCondition($expr);
}
return $xpath;
/* FIXME: handle an+b, odd, even
an+b means every-a, plus b, e.g., 2n+1 means odd
0n+b means b
n+0 means a=1, i.e., all elements
an means every a elements, i.e., 2n means even
-n means -1n
-1n+6 means elements 6 and previous */
}