private string BuildChapterHtml(EpubChapterHolder cHolder)
        {
            string result               = string.Empty;
            int    startTagPosition     = 0; // string position of this chapter's id
            int    lengthOfRequiredText = 0; // the number of chars between the start of the chapter and the start of the next chapter (or end of the file if the next chapter isn't in the same file)

            // Load current chapter html into HtmlAgilityPack to parse
            // Method:  Find the string position of the start and end id's of this chapter, then just grab the chars between them using .Substring(). (This is a much faster method than using xpath to select the relevant nodes).
            //          Then load the result into HtmlAgilityPack because it will fix any html issues i.e. close any unclosed tags etc

            var doc = new HtmlDocument();

            doc.LoadHtml(cHolder.CurrentChapter.EpubChapter.HtmlContentFileRef.ReadContentAsText() ?? "");                                    //.ReadHtmlContent() ?? "");

            var bodyNodes = doc.DocumentNode.SelectSingleNode("//body");                                                                      // select everything inside the <body> tag

            var startNode = bodyNodes.SelectSingleNode(string.Format("//node()[@id='{0}']", cHolder.CurrentChapter.EpubChapter.Link.Anchor)); // return the start node i.e. the start of the current chapter
            var startTag  = startNode.OuterHtml;

            startTagPosition = bodyNodes.InnerHtml.IndexOf(startTag);                                                                        // index of the start tag

            if (!string.IsNullOrEmpty(cHolder.NextChapter.EpubChapter?.Link.Anchor ?? ""))                                                   // there is a next Chapter
            {
                var endNode = bodyNodes.SelectSingleNode(string.Format("//node()[@id='{0}']", cHolder.NextChapter.EpubChapter.Link.Anchor)); // return the end node i.e. the start of the next chapter
                if (endNode != null)                                                                                                         // next chapter found
                {
                    var endTag         = endNode.OuterHtml;
                    int endTagPosition = bodyNodes.InnerHtml.IndexOf(endTag); // index of the end tag
                    lengthOfRequiredText = endTagPosition - startTagPosition;
                }
                else // next chapter is not in this chapter file
                {
                    // don't need to do anything here, as lengthOfRequiredText will remain 0
                }
            }

            var theHtml = string.Empty;

            if (lengthOfRequiredText > 0)                                                        // there is a next tag
            {
                theHtml = bodyNodes.InnerHtml.Substring(startTagPosition, lengthOfRequiredText); // return the content beteen the start of the start tag and the start of the end tag
            }
            else // no end tag so just get all the content to the end of the body
            {
                theHtml = bodyNodes.InnerHtml.Substring(startTagPosition);
            }


            // update all chapter links to use the friendly url
            var charSetOccurences = new Regex("href=\"(.+)#([^\"]+)\"", RegexOptions.IgnoreCase); // find all href links with anchors
            var charSetMatches    = charSetOccurences.Matches(theHtml);

            foreach (Match match in charSetMatches)
            {
                if (theHtml.IndexOf(string.Format(@"id=""{0}""", match.Groups[2].Value)) > 0) // the matching id tag has been found, so update the href to remove the url before the #
                {
                    theHtml = theHtml.Replace(match.Groups[1].Value + "#" + match.Groups[2].Value, "#" + match.Groups[2].Value);
                }
            }

            // validate/fix html
            doc.LoadHtml(theHtml ?? ""); // by now loading the resultant html into the HtmlDocument object this should fix any html issues i.e. close any unclosed tags etc
            result = doc.DocumentNode.OuterHtml;

            // now add any sub chapters
            result = result + BuildSubChapters(cHolder.CurrentChapter.EpubChapter, "", true);

            return(result);
        }
        /// <summary>
        /// Display the chapter. This might be a whole xhtml file or a section of an xhtml file between 2 'chapter' id's (or epub navnodes)
        /// </summary>
        /// <param name="ePubDisplayModel"></param>
        /// <param name="epubBookRef"></param>
        public void FindAndProcessChapter(ref EpubDisplayModel ePubDisplayModel, EpubBookRef epubBookRef)
        {
            EpubChapterHolder cHolder = new EpubChapterHolder();

            // Enumerating chapters
            var allChapters = epubBookRef.GetNavigation();//.GetChapters();

            for (int i = 0; i < allChapters.Count(); i++)
            {
                var    _chapter = allChapters[i];
                string encTitle = EpubHelpers.EncodeChapterTitleForUrl(_chapter.Title);

                if (encTitle == _processAction && !cHolder.CurrentChapter.IsValid()) // chapter found! select this chapter to display
                {
                    cHolder.CurrentChapter.ChapterIndex = i;
                    cHolder.CurrentChapter.EpubChapter  = _chapter;
                    cHolder.CurrentChapter.TitleAndLinkUrl.LinkTitle = _chapter.Title;
                }

                ePubDisplayModel.TOC_Items.Add(new EpubLink()
                {
                    LinkTitle = _chapter.Title
                });                                                                            // add TOC to display model
            }

            if (!cHolder.CurrentChapter.IsValid())                             // chapter not found - so get the default chapter and redirect to that
            {
                if (_startAtIndex < 0 || _startAtIndex >= allChapters.Count()) // check if the _startAtIndex property is within valid limits - if not then set the index to 0
                {
                    _startAtIndex = 0;
                }

                var _chapter = allChapters[_startAtIndex];
                cHolder.CurrentChapter.TitleAndLinkUrl.LinkTitle = _chapter.Title;

                ePubDisplayModel.RedirectToChapter = cHolder.CurrentChapter.TitleAndLinkUrl.LinkUrl;
                return; // exit this method as we need to perform a redirect in the calling controller rather than
            }

            ePubDisplayModel.TOC_Items[cHolder.CurrentChapter.ChapterIndex].IsCurrent = true;


            // try and find the previous chapter details
            int previousChapterIndex = cHolder.CurrentChapter.ChapterIndex - 1;

            if (previousChapterIndex >= 0) // check index is valid
            {
                var _chapter = allChapters[previousChapterIndex];
                cHolder.PreviousChapter.ChapterIndex = previousChapterIndex;
                cHolder.PreviousChapter.EpubChapter  = _chapter;
                cHolder.PreviousChapter.TitleAndLinkUrl.LinkTitle = _chapter.Title;

                ePubDisplayModel.Nav_PreviousChapterLink.LinkTitle = _chapter.Title;
            }

            // try and find the next chapter details
            int nextChapterIndex = cHolder.CurrentChapter.ChapterIndex + 1;

            if (nextChapterIndex < allChapters.Count()) // check index is valid
            {
                var _chapter = allChapters[nextChapterIndex];
                cHolder.NextChapter.ChapterIndex = nextChapterIndex;
                cHolder.NextChapter.EpubChapter  = _chapter;
                cHolder.NextChapter.TitleAndLinkUrl.LinkTitle = _chapter.Title;

                ePubDisplayModel.Nav_NextChapterLink.LinkTitle = _chapter.Title;
            }

            ePubDisplayModel.ChapterHtml = BuildChapterHtml(cHolder);
        }