/**
* 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 - 1);
}
$xpath->addCondition(sprintf('position() = %s', $b));
return $xpath;
}
if ($a < 0) {
if ($b < 1) {
$xpath->addCondition('false()');
return $xpath;
}
$sign = '<=';
} else {
$sign = '>=';
}
$expr = 'position()';
if ($last) {
$expr = 'last() - ' . $expr;
$b--;
}
if (0 !== $b) {
$expr .= ' - ' . $b;
}
$conditions = array(sprintf('%s %s 0', $expr, $sign));
if (1 !== $a && -1 !== $a) {
$conditions[] = sprintf('(%s) mod %d = 0', $expr, $a);
}
$xpath->addCondition(implode(' and ', $conditions));
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 */
}