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 void ReplaceNamedSdcMinObsAlternatives(List <Template.Page> pages, Dictionary <string, int> sdcMinObsAlternatives, ErrorCollector errorCollector)
        {
            foreach (Template.Page page in pages)
            {
                foreach (Template.Page.Table table in page.tables)
                {
                    if (table.sdcDefinition.minObsAlternative == null && table.sdcDefinition.minObsAlternativeName != null)
                    {
                        Replace(ref table.sdcDefinition);
                        foreach (Template.Page.Table.Row row in table.rows)
                        {
                            Replace(ref row.sdcDefinition);
                        }
                        foreach (Template.Page.Table.Column column in table.columns)
                        {
                            Replace(ref column.sdcDefinition);
                        }
                        foreach (Template.Page.Table.Column column in table.reformColumns)
                        {
                            Replace(ref column.sdcDefinition);
                        }
                        foreach (Template.Page.Table.Cell cell in table.cells)
                        {
                            Replace(ref cell.sdcDefinition);
                        }
                        foreach (Template.Page.Table.Cell cell in table.reformCells)
                        {
                            Replace(ref cell.sdcDefinition);
                        }
                    }
                }
            }

            void Replace(ref Template.Page.Table.SDCDefinition sdcDefinition)
            {
                if (sdcDefinition.minObsAlternativeName == null)
                {
                    return;
                }
                if (int.TryParse(sdcDefinition.minObsAlternativeName, out int i))
                {
                    sdcDefinition.minObsAlternative = i;
                }
                else
                {
                    if (sdcMinObsAlternatives.ContainsKey(sdcDefinition.minObsAlternativeName))
                    {
                        sdcDefinition.minObsAlternative = sdcMinObsAlternatives[sdcDefinition.minObsAlternativeName];
                    }
                    else
                    {
                        errorCollector.AddDebugOnlyError($"Unknown SdcMinObsAlternative '{sdcDefinition.minObsAlternativeName}'.");
                    }
                }
            }
        }
        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;
                }
            }
        }