using System;
using System.Xml;
 
namespace TestCAX
{
   class Program
   {
          //Demonstration C# program for CAX, caching API for XML
        static void Main(string[] args)
       {
            Demo d = new Demo();
           d.printShakespeare();
       }
        public class Demo
       {
            public void printShakespeare()
           {
                //creates an instance of CAX, parses much_ado.xml, then uses CAX methods
               //to retrieve  speeches in ACT III and V and write the lines to the console.
               string xmlfile = Environment.CurrentDirectory + @"\much_ado.xml";
               //create an XmlReaderSettings object to pass to the CAX constructor
               XmlReaderSettings settings = new XmlReaderSettings();
               settings.ProhibitDtd = false;
               settings.XmlResolver = null;
               settings.ConformanceLevel = ConformanceLevel.Auto;
               //create an instance of CAX using the xmlfile and settings
               CAX.XReader xc = null;
               try
               {
                    xc = new CAX.XReader(xmlfile, settings);
               }
                catch (CAX.CAXException xcex)
               {
                    Console.WriteLine(xcex.Message);
                   Console.ReadLine();
                   return;
               }
                catch (UnauthorizedAccessException uaex)
               {
                    Console.WriteLine(uaex.Message);
                   Console.ReadLine();
                   return;
               }
                catch (NullReferenceException nrex)
               {
                    Console.WriteLine(nrex.Message);
                   Console.ReadLine();
                   return;
               }
                catch (System.Security.SecurityException secex)
               {
                    Console.WriteLine(secex.Message);
                   Console.ReadLine();
                   return;
               }
                //parse the  xml
               while (xc.EOF == false)
               {
                    try
                   {
                        xc.Read();
                       //read past ACT V and print ACT III to demonstrate that CAX can retrieve previously
                       //parsed data at any time without changing the position of the underlying XmlReader.
                       if (xc.Value == "ACT V")
                       {
                            //print the first speech in ACT III
                           printSpeech(xc, "ACT III");
                       }
                    }
                    catch (XmlException xex)
                   {
                        Console.WriteLine(xex.Message);
                       Console.ReadLine();
                       return;
 
                   }
                    catch (CAX.CAXException xcex)
                   {
                        Console.WriteLine(xcex.Message);
                       Console.ReadLine();
                       return;
                   }
                }
                //now that the entire xml has been parsed print the first speech in ACT V
               printSpeech(xc, "ACT V");
               //close the CAX, which also closes the underlying xmlReader
               xc.Close();
           }
 
            private void printSpeech(CAX.XReader xc, string act)
           {
 
                //move the CAX to the root element
               if (xc.CursorMoveToRoot() == false) return;
               //move to the first ACT descendant
               xc.CursorMoveToDescendent("ACT");
               bool done = false;
               //move through the entire xml until the desired content is located
               while (xc.CursorEOB == false && done == false)
               {
                    //move to the TITLE of ACT
                   if (xc.CursorMoveToDescendent("TITLE"))
                   {
                        //skip to the text node
                       xc.CursorSkip(1);
                   }
                    //if the text node is ACT III, move to the first speech and write it out
                   if (xc.CursorNodetype == XmlNodeType.Text && xc.CursorValue == act)
                   {
                        if (xc.CursorMoveToFollowing("SCENE") && xc.CursorMoveToDescendent("SPEECH"))
                       {
                            string name = xc.CursorName;
                           //move to to speaker
                           xc.CursorMoveToFollowing("SPEAKER");
                           //skip to the text node and write the speaker's name
                            xc.CursorSkip(1);
                           Console.WriteLine(xc.CursorValue);
                           while (xc.CursorEOB == false)
                           {
                                if (xc.CursorName == "LINE" && xc.CursorNodetype == XmlNodeType.Element)
                               {
                                    //skip to text
                                   xc.CursorSkip(1);
                                   if (xc.CursorNodetype == XmlNodeType.Text)
                                   {
                                        Console.WriteLine(xc.CursorValue);
                                   }
                                }
                                //skip past LINE endelement to the next ELEMENT.
                               xc.CursorSkip(2);
                               //if the SPEAKER endelement is reached, we are done.
                               if (xc.CursorName == name && xc.CursorNodetype == XmlNodeType.EndElement)
                               {
                                    done = true;
                                   break;
                               }
                            }
                        }
                    }
                    xc.CursorMoveToFollowing("ACT");
               }
                Console.ReadLine();