private QilNode PlaceMarker(QilNode countPattern, QilNode fromPattern, bool multiple)
{
/*
Quotation from XSLT 2.0 spec:
* Let $A be the node sequence selected by the expression
ancestor-or-self::node()[matches-count(.)] (level = "multiple")
ancestor-or-self::node()[matches-count(.)][1] (level = "single")
* Let $F be the node sequence selected by the expression
ancestor-or-self::node()[matches-from(.)][1]
* Let $AF be the value of
$A intersect ($F/descendant-or-self::node())
* Return the result of the expression
for $af in $AF return 1+count($af/preceding-sibling::node()[matches-count(.)])
NOTE: There are some distinctions between XSLT 1.0 and XSLT 2.0 specs. In our 1.0 implementation we:
1) Assume that the 'matches-from()' function does not match root nodes by default.
2) Instead of '$A intersect ($F/descendant-or-self::node())' (which, by the way,
would filter out attribute and namespace nodes from $A) we calculate
'$A' if the 'from' attribute is omitted,
'$A[. >> $F]' if the 'from' attribute is present.
*/
QilNode countPattern2, countMatches, fromMatches, A, F, AF;
QilIterator i, j;
countPattern2 = (countPattern != null) ? countPattern.DeepClone(_f.BaseFactory) : null;
countMatches = _f.Filter(i = _f.For(_f.AncestorOrSelf(GetCurrentNode())), MatchCountPattern(countPattern, i));
if (multiple)
{
A = _f.DocOrderDistinct(countMatches);
}
else
{
A = _f.Filter(i = _f.For(countMatches), _f.Eq(_f.PositionOf(i), _f.Int32(1)));
}
if (fromPattern == null)
{
AF = A;
}
else
{
fromMatches = _f.Filter(i = _f.For(_f.AncestorOrSelf(GetCurrentNode())), MatchPattern(fromPattern, i));
F = _f.Filter(i = _f.For(fromMatches), _f.Eq(_f.PositionOf(i), _f.Int32(1)));
AF = _f.Loop(i = _f.For(F), _f.Filter(j = _f.For(A), _f.Before(i, j)));
}
return _f.Loop(j = _f.For(AF),
_f.Add(_f.Int32(1), _f.Length(_f.Filter(i = _f.For(_f.PrecedingSibling(j)), MatchCountPattern(countPattern2, i))))
);
}