Przykładowy dokument wejściowy

<EventInput>
  <Event Id="100="><test>a</test></Event>
  <Event Id="101="><test>b</test></Event>
  <Event Id="102="><test>c</test></Event>
  <Event Id="103="><test>d</test></Event>
  <Event Id="104="><test>e</test></Event>
  <Event Id="105="><test>f</test></Event>
  <Event Id="106="><test>g</test></Event>
  <Event Id="107="><test>h</test></Event>
  <Event Id="108="><test>i</test></Event>
  <Event Id="109="><test>j</test></Event>
  <Event Id="110="><test>k</test></Event>
  <Event Id="111="><test>l</test></Event>
  <Event Id="112="><test>m</test></Event>
  <Event Id="113="><test>n</test></Event>
  <Event Id="114="><test>o</test></Event>
  <Event Id="115="><test>p</test></Event>
  <Event Id="116="><test>q</test></Event>
  <Event Id="117="><test>r</test></Event>
  <Event Id="118="><test>s</test></Event>
  <Event Id="119="><test>t</test></Event>
  <Event Id="120="><test>u</test></Event>
  <Event Id="121="><test>w</test></Event>
  <Event Id="122="><test>v</test></Event>
  <Event Id="123="><test>x</test></Event>
  <Event Id="124="><test>y</test></Event>
  <Event Id="125="><test>z</test></Event>
  <Event Id="126="><test>1</test></Event>
  <Event Id="127="><test>2</test></Event>
  <Event Id="128="><test>3</test></Event>
  <Event Id="129="><test>4</test></Event>
</EventInput>

Paginacja za pomocą XmlReadera

   class Program {

        public static void Main(string[] args) {
            Console.WriteLine(new Program().GetPage(@"test.xml", 2, 7).OuterXml);
        }

        // Zwraca dokument Xml zawierajacy rekordy dla zadanej strony
        private XmlDocument GetPage(string inputUri, int pageNumber, int pageSize) {
            if(pageNumber < 1) {
                throw new ArgumentException("Invalid pageNumber.", "pageNumber");
            }

            if(pageSize < 1) {
                throw new ArgumentException("Incorrect pageSize.", "pageSize");
            }


            // Tutaj bedzie zapisany wynikowy Xml zawierajacy rekordy dla zadanej strony
            XmlDocument pageXml = new XmlDocument();
            pageXml.LoadXml("<page />");
            
            // Ustaw XmlReadera na pierwszy element potomny elementu root
            using(XmlReader xr = XmlReader.Create(inputUri)) {
                while(xr.Depth == 0) {
                    if(!xr.Read()) {
                        return pageXml;
                    }
                }

                // Przeskocz rekordy ktore nie maja byc wyswietlone. W przypadku osiagniecia konca 
                // pliku stworz ostatnia strone i zapisz w zmiennej pageXml.
                SkipRecords(pageXml, xr, (pageNumber - 1) * pageSize, pageSize);

                // Jesli pageXml nie zawiera jeszcze wynikow (bedacych ostatnia strona)
                if(!pageXml.DocumentElement.HasChildNodes) {
                    // Stworz wyniki dla biezacej strony
                    for(int nodeNum = 0; nodeNum < pageSize && !xr.EOF; nodeNum++) {
                        using(XmlReader currRecordReader = xr.ReadSubtree()) {
                            XmlNode xn = pageXml.ReadNode(currRecordReader);
                            pageXml.DocumentElement.AppendChild(xn);
                            currRecordReader.Close();
                        }
                        xr.Skip();
                        ReadToNextElement(xr);
                    }
                }
            }

            return pageXml;
        }


        // Funkcja przeskakuje rekordy ktorych nie chcemy wyswietlac. Po wyjsciu z funkcji XmlReader 
        // jest ustawiony na elemencie bedacym pierwszym rekordem do wyswietlenia. Jesli liczba rekordow
        // do przeskoczenia jest wieksza od liczby rekordow w dokumencie rekordy z ostatniej strony 
        // dodawane są do obiektu pageXml.
        private void SkipRecords(XmlDocument pageXml, XmlReader xr, int numNodesToSkip, int pageSize) {
            Debug.Assert(pageSize > 0, "pageSize has to greater than 0");

            // tablica zawiera wezly dla aktualnie przetwarzanej strony na wypadek gdyby ta strona
            // okazala sie ostatnia (np. gdy liczba rekordów do przeskoczenia jest wieksza od 
            // liczby wszystkich rekordow)
            string[] potentialLastPage = new string[pageSize];

            int nodeIdx = 0;
            for(; nodeIdx < numNodesToSkip; nodeIdx++) {
                // Ustaw XmlReadera na nastepnym wezle typu element
                ReadToNextElement(xr); 
                
                if(xr.EOF) {
                    // Osiagnelismy koniec dokumentu
                    break;
                }
                // Zachowaj rekord na wypadek gdyby strona okazala sie ostatnia
                potentialLastPage[nodeIdx % pageSize] = xr.ReadOuterXml();
            }

            // Ustaw XmlReadera na nastepnym wezle typu element. Jesli po tej operacji
            // xr.EOF == false to XmlReader jest ustawiony na pierwszym rekordzie "do wyswietlenia"
            ReadToNextElement(xr);

            // Osiagniety koniec dokumentu - stworz ostatnia strone
            if(xr.EOF) {
                pageXml.DocumentElement.InnerXml =
                    string.Join(string.Empty, potentialLastPage, 0, nodeIdx % pageSize == 0 ? pageSize : nodeIdx % pageSize);
            }
        }

        // Ustawia XmlReader na najblizszym wezle typu Element
        private void ReadToNextElement(XmlReader xr) {
            while(xr.NodeType != XmlNodeType.Element && !xr.EOF) {
                xr.Read();
            }
        }
    }