internal List<Monster> Parse(MonsterParser parser, WikiPage page, WikiExport wikiExport)
        {
            WikiName redirection;
            var count = 0;
            while (page.IsRedirection(out redirection))
            {
                page = Wiki.Pages[redirection];
                count++;

                if (count > 10)
                {
                    throw new InvalidOperationException("Boucle de redirections détectée");
                }
            }

            var raw = page.Raw;

            var result = parser.ParseAll(page, raw);

            if (result.Count == 0)
            {
                throw new InvalidOperationException("Aucun bloc BD détecté");
            }

            return result;
        }
        internal bool TryParse(MonsterParser parser, WikiPage monsterPage, WikiExport wikiExport, out List<Monster> monster, ILog log)
        {
            try
            {
                monster = Parse(parser, monsterPage, wikiExport);
                return true;
            }
            catch (Exception ex)
            {
                log.Error("Page \"{0}\" (id '{1}') : {2}",
                    monsterPage.Name,
                    monsterPage.Id,
                    ex.RecursiveMessage());
                monster = null;

                return false;
            }
        }
        private void LoadPage(XmlSerializer serializer, string subDir, string fileName)
        {
            // Désérialisation page
            XmlWikiPage xmlPage;
            using (var reader = new StreamReader(fileName))
            {
                xmlPage = (XmlWikiPage) serializer.Deserialize(reader);
                xmlPage.FileName = fileName;
            }

            if (string.IsNullOrWhiteSpace(xmlPage.FullName))
            {
                throw new ApplicationException(string.Format("La page du fichier {0} ne contient pas de nom complet", fileName));
            }

            var name = new WikiName(xmlPage.FullName);

            // Chargement catégories
            foreach (var categoryName in xmlPage.Categories)
            {
                var category = WikiName.FromString(categoryName);
                if (!categories.ContainsKey(category))
                {
                    categories.Add(category, category);
                }
            }

            // Chargement page
            var page = new WikiPage(this, xmlPage);
            pages.Add(name, page);

            // Chargement liens entrants
            ICollection<WikiName> targets;
            foreach (var linkName in xmlPage.InLinksNames)
            {
                if (!links.TryGetValue(linkName, out targets))
                {
                    targets = new HashSet<WikiName>();
                    links[linkName] = targets;
                }

                if (!targets.Contains(name))
                {
                    targets.Add(name);
                }
            }

            // Chargement liens sortants
            if (!links.TryGetValue(name, out targets))
            {
                targets = new HashSet<WikiName>();
                links[name] = targets;
            }

            foreach (var linkName in xmlPage.OutLinksNames)
            {
                if (!targets.Contains(name))
                {
                    targets.Add(name);
                }
            }
        }