public WikiPage(WikiExport wiki, XmlWikiPage source)
        {
            this.wiki = wiki;
            this.source = source;
            displayName = source.Title;
            wikiName = WikiName.FromString(source.FullName);

            Url = string.Format("http://www.pathfinder-fr.org/Wiki/Pathfinder-RPG.{0}.ashx", Name);
        }
        private static void Main(string[] args)
        {
            Console.WriteLine("Pathfinder-fr Wiki Export Parser v{0}", typeof (Program).Assembly.GetName().Version);

            allCommands = new List<ICommand>();
            allCommands.AddRange(CommandLoader.LoadCommandFromAssemblyOf(typeof (ICommand)));
            #if DEBUG
            allCommands.AddRange(CommandLoader.LoadCommandFromAssemblyOf(typeof (ScanConjurateurCommand)));
            #endif

            if (args == null || args.Length < FixedArgs || args.Any(x => x.Equals("/help", StringComparison.OrdinalIgnoreCase)))
            {
                ShowHelp();
                return;
            }

            Console.WriteLine();

            var xmlPath = args[0];
            var xmlOut = args[1];
            var commandName = args[2];

            if (!Directory.Exists(xmlPath))
            {
                Console.WriteLine("ERREUR: Le dossier spécifié {0} n'existe pas", xmlPath);
                return;
            }

            var options = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            var commandNames = new List<string>();

            foreach (var arg in args.Skip(FixedArgs))
            {
                if (arg[0] == '/')
                {
                    if (arg.Length > 1)
                    {
                        var i = arg.IndexOf(':');

                        if (i == -1 || i == 1 || i == arg.Length - 1)
                        {
                            options.Add(arg.Substring(1), string.Empty);
                        }
                        else
                        {
                            options.Add(arg.Substring(1, i - 1), arg.Substring(i + 1));
                        }
                    }
                }
                else
                {
                    commandNames.Add(arg);
                }
            }

            Console.WriteLine("Commandes à exécuter :");
            var commands = LoadCommands(allCommands, commandName, commandNames);
            foreach (var command in commands)
            {
                Console.WriteLine("- {0}", command.Alias);
            }

            Console.WriteLine("Chargement de l'export wiki...");
            var export = new WikiExport();
            export.Load(xmlPath);

            ILog log = new ConsoleLog();
            FileLog fileLog = null;

            try
            {
                var dataSets = new DataSetCollection();
                dataSets.Lang = "fr-FR";

                string logFileName;
                if (options.TryGetValue("log", out logFileName))
                {
                    fileLog = new FileLog(logFileName);
                    log = new CombineLog(log, fileLog);
                }

                foreach (var command in commands)
                {
                    log.Information("Exécution commande {0}", command.Alias);
                    command.Wiki = export;
                    command.Log = log;
                    command.Execute(dataSets);
                }

                // Serialisation
                var directory = Path.GetDirectoryName(xmlOut);
                if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                var writers = new IDataSetWriter[]
                {
                    new XmlDataSetWriter(),
                    new JsonDataSetWriter(),
                    new CsvDataSetWriter(),
                    new XmlSingleDataSetWriter()
                };

                if (options.Any(o => string.Equals(o.Key, "unique", StringComparison.OrdinalIgnoreCase)))
                {
                    // un seul fichier
                    var mergedDataSet = new DataSet();
                    foreach (var dataSet in dataSets.DataSets)
                    {
                        mergedDataSet.Add(dataSet.Value);
                    }

                    foreach (var writer in writers.Where(w => w.Accept("", mergedDataSet, options)))
                    {
                        writer.Write("", mergedDataSet, xmlOut);
                    }

                }
                else
                {
                    // un fichier par dataset

                    foreach (var dataSet in dataSets.DataSets)
                    {
                        foreach (var writer in writers.Where(w => w.Accept(dataSet.Key, dataSet.Value, options)))
                        {
                            writer.Write(dataSet.Key, dataSet.Value, xmlOut);
                        }
                    }
                }
            }
            finally
            {
                if (fileLog != null)
                {
                    fileLog.Dispose();
                }
            }

            #if DEBUG
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
            #endif
        }
        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;
            }
        }
        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;
        }