private static Template.TemplateInfo ReadInfo(XElement xeInfo, ErrorCollector errorCollector)
        {
            Template.TemplateInfo info = new Template.TemplateInfo();

            if (xeInfo.Element("DebugMode") != null && errorCollector.XEleGetBool(xeInfo.Element("DebugMode"), xeInfo))
            {
                errorCollector.SetDebugMode();
            }

            foreach (XElement xe in xeInfo.Elements())
            {
                if (xe.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xe))
                {
                case "Name": info.name = xe.Value; break;

                case "Title": info.title = xe.Value; break;

                case "Subtitle": info.subtitle = xe.Value; break;

                case "Button": info.button = xe.Value; break;

                case "Description": info.description = xe.Value; break;

                case "GeneralDescription": info.generalDescription = xe.Value; break;

                case "MinFiles": info.minFiles = errorCollector.XEleGetInt(xe, xeInfo); break;

                case "MaxFiles": info.maxFiles = errorCollector.XEleGetInt(xe, xeInfo); break;

                case "HideMainSelectorForSingleFilePackage": info.HideMainSelectorForSingleFilePackage = errorCollector.XEleGetBool(xe, xeInfo); break;

                case "TemplateType": info.templateType = errorCollector.XEleGetEnum <HardDefinitions.TemplateType>(xe, xeInfo); break;

                case "AdditionalCalculationLevels": info.calculationLevels = ReadElementGroup(xe, ReadCalculationLevel, errorCollector); break;

                case "RequiredVariables": info.requiredVariables = ReadElementGroup(xe, ReadRequiredVariable, errorCollector); break;

                case "OptionalVariables": info.optionalVariables = ReadElementGroup(xe, ReadOptionalVariable, errorCollector); break;

                case "UserVariables": info.userVariables = ReadElementGroup(xe, ReadUserVariable, errorCollector); break;

                case "SDCDefinition": ReadTemplateInfoSDCDefinition(errorCollector, info, xe); break;

                case "ExportDescriptionMode": info.exportDescriptionMode = errorCollector.XEleGetEnum <HardDefinitions.ExportDescriptionMode>(xe, xeInfo); break;

                case "DebugMode": break;

                default: errorCollector.AddXmlUnkownEleError(xe, xeInfo); break;
                }
            }
            ;
            return(info);
        }
        private static DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Axis ReadAxis(XElement xeAxis, ErrorCollector errorCollector)
        {
            DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Axis axis = new DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Axis();
            foreach (XElement xe in xeAxis.Elements())
            {
                if (xe.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xe))
                {
                case "Label": axis.label = xe.Value; break;

                case "ValuesFrom": axis.valuesFrom = xe.Value; break;

                case "StartFromZero": axis.startFromZero = errorCollector.XEleGetBool(xe, xeAxis); break;

                case "Interval": axis.interval = errorCollector.XEleGetInt(xe, xeAxis); break;

                case "LabelDocking": axis.labelDocking = xe.Value; break;

                default: errorCollector.AddXmlUnkownEleError(xe, xeAxis); break;
                }
            }
            return(axis);
        }
        private static DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Series ReadGraphSerie(XElement xeSerie, ErrorCollector errorCollector)
        {
            DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Series serie = new DisplayResults.DisplayPage.DisplayTable.DisplayGraph.Series();
            foreach (XElement xe in xeSerie.Elements())
            {
                if (xe.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xe))
                {
                case "Visible": serie.visible = errorCollector.XEleGetBool(xe, xeSerie); break;

                case "Name": serie.name = xe.Value; break;

                case "Size": serie.size = errorCollector.XEleGetInt(xe, xeSerie); break;

                case "Colour": serie.colour = xe.Value; break;

                case "Type": serie.type = xe.Value; break;

                case "MarkerStyle": serie.markerStyle = xe.Value; break;

                default: errorCollector.AddXmlUnkownEleError(xe, xeSerie); break;
                }
            }
            return(serie);
        }
        private static KeyValuePair <string, int> ReadSdcMinObsAlternative(XElement xeAlt, ErrorCollector errorCollector)
        {
            string name = null; int minObs = int.MinValue;

            foreach (XElement xe in xeAlt.Elements())
            {
                if (xe.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xe))
                {
                case "Name": name = xe.Value; break;

                case "MinObs": minObs = errorCollector.XEleGetInt(xe, xeAlt); break;

                default: errorCollector.AddXmlUnkownEleError(xe, xeAlt); break;
                }
            }
            if (minObs == int.MinValue || name == null)
            {
                errorCollector.AddDebugOnlyError("Incomplete definition of SdcMinObsAlternative" +
                                                 (name == null ? ": missing 'Name'" : $" '{name}': ") +
                                                 (minObs == int.MinValue ? "missing 'MinObs'" : string.Empty));
            }
            return(new KeyValuePair <string, int>(name, minObs));
        }
        private static Template.Page.Table.Cell ReadCell(XElement xeCell, ErrorCollector errorCollector)
        {
            Template.Page.Table.Cell cell = new Template.Page.Table.Cell();
            foreach (XElement xe in xeCell.Elements())
            {
                if (xe.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xe))
                {
                case "ColNum": cell.colNum = errorCollector.XEleGetInt(xe, xeCell); break;

                case "RowNum": cell.rowNum = errorCollector.XEleGetInt(xe, xeCell); break;

                case var ctf when commonTableFields.Contains(ctf): ReadCommonTableField(xe, cell, errorCollector, xeCell); break;

                default: errorCollector.AddXmlUnkownEleError(xe, xeCell); break;
                }
            }
            return(cell);
        }
        private static void ReadTemplateInfoSDCDefinition(ErrorCollector errorCollector, Template.TemplateInfo info, XElement xe)
        {
            foreach (XElement xeg in xe.Elements())
            {
                if (xeg.Value == null)
                {
                    continue;
                }
                switch (GetXEleName(xeg))
                {
                case "HideZeroObs": info.sdcHideZeroObs = errorCollector.XEleGetBool(xeg, xe); break;

                case "MinObsDefault": info.sdcMinObsDefault = errorCollector.XEleGetInt(xeg, xe); break;

                case "MinObsAlternatives":
                    info.sdcMinObsAlternatives = new Dictionary <string, int>(StringComparer.OrdinalIgnoreCase);
                    foreach (var ele in ReadElementGroup(xeg, ReadSdcMinObsAlternative, errorCollector))
                    {
                        if (ele.Key == null)
                        {
                            continue;
                        }
                        if (info.sdcMinObsAlternatives.ContainsKey(ele.Key))
                        {
                            errorCollector.AddDebugOnlyError($"Double definition of SdcMinObsAlternative '{ele.Key}'.");
                        }
                        else
                        {
                            info.sdcMinObsAlternatives.Add(ele.Key, ele.Value);
                        }
                    }
                    break;

                default: errorCollector.AddXmlUnkownEleError(xeg, xe); break;
                }
            }
        }