/// <summary>
        /// Gets all Group-Item names at the given <see cref="xPath"/>
        /// </summary>
        /// <param name="xPath"></param>
        /// <returns></returns>
        internal static IVoca[] GetDomusOpesItemNames(string xPath)
        {
            if (String.IsNullOrWhiteSpace(xPath))
            {
                return(null);
            }

            OpesXml = OpesXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_DOMUS_OPES,
                                                                        Assembly.GetExecutingAssembly());
            var nodes = OpesXml.SelectNodes(xPath);

            if (nodes == null || nodes.Count <= 0)
            {
                return(null);
            }
            var names = new List <IVoca>();

            foreach (var o in nodes)
            {
                if (!(o is XmlNode node))
                {
                    continue;
                }
                if (TryParseUsDomusOpesXml(node, out var nameOut))
                {
                    names.Add(nameOut);
                }
            }
            return(names.ToArray());
        }
Example #2
0
        /// <summary>
        /// Gets the base dollar value of the given factor
        /// </summary>
        /// <param name="tbl"></param>
        /// <returns></returns>
        public static double GetFactorBaseValue(AmericanFactorTables tbl)
        {
            DebtXml = DebtXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_PERSONAL_DEBT,
                                                                        Assembly.GetExecutingAssembly());
            WealthXml = WealthXml ??
                        XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_PERSONAL_WEALTH, Assembly.GetExecutingAssembly());


            var xmlDoc = tbl == AmericanFactorTables.CreditCardDebt || tbl == AmericanFactorTables.HomeDebt ||
                         tbl == AmericanFactorTables.VehicleDebt || tbl == AmericanFactorTables.OtherDebt
                ? DebtXml
                : WealthXml;
            var tblName  = Enum.GetName(typeof(AmericanFactorTables), tbl);
            var tblXPath = $"//table[@name='{tblName}']";
            var tblNode  = xmlDoc.SelectSingleNode(tblXPath) as XmlElement;

            if (string.IsNullOrWhiteSpace(tblNode?.Attributes?["value"]?.Value))
            {
                return(0.0D);
            }
            if (!double.TryParse(tblNode.Attributes["value"].Value, out var dblOut))
            {
                return(0.0D);
            }
            return(dblOut);
        }
Example #3
0
        /// <summary>
        /// Gets High Schools based on US Postal Zip Code
        /// </summary>
        /// <param name="zipCode">
        /// Either a 3 digit prefix or the full 5 digit code.
        /// </param>
        /// <returns></returns>
        public static AmericanHighSchool[] GetHighSchoolsByZipCode(string zipCode)
        {
            zipCode = zipCode ?? "";
            zipCode = new string(zipCode.ToCharArray().Where(char.IsDigit).ToArray());
            if (string.IsNullOrWhiteSpace(zipCode))
            {
                return(GetHighSchoolsByState());
            }

            HsXml = HsXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_HIGH_SCHOOL_DATA,
                                                                    Assembly.GetExecutingAssembly());
            if (HsXml == null)
            {
                return new[] { GetDefaultHs() }
            }
            ;

            var xpath = zipCode.Length == 3
                        ? $"//zip-code[@prefix='{zipCode}']//high-school"
                        : $"//zip-stat[@value='{zipCode}']/high-school";

            //just get this once for all
            var stateXpath  = $"{xpath}/../../..";
            var stateName   = "";
            var stateAbbrev = "";
            var stateNode   = HsXml.SelectSingleNode(stateXpath);

            if (stateNode?.Attributes != null)
            {
                var attr = stateNode.Attributes["name"];

                stateName = attr.Value;

                attr        = stateNode.Attributes["abbreviation"];
                stateAbbrev = attr.Value;
            }

            var elements = HsXml.SelectNodes(xpath);

            if (elements == null || elements.Count <= 0)
            {
                return(GetHighSchoolsByState());
            }

            var parsedList = ParseHighSchoolsFromNodeList(elements);

            foreach (var hs in parsedList)
            {
                hs.StateAbbrev = stateAbbrev;
                hs.StateName   = stateName;
            }
            return(parsedList);
        }
        internal static string[] GetAllowZeroNames(DomusOpesDivisions division, string groupName)
        {
            if (string.IsNullOrWhiteSpace(groupName))
            {
                return new string[] {}
            }
            ;
            var xPath = $"//{division.ToString().ToLower()}/group[@name='{groupName}']/item";

            OpesXml = OpesXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_DOMUS_OPES,
                                                                        Assembly.GetExecutingAssembly());
            var nodes = OpesXml.SelectNodes(xPath);

            if (nodes == null || nodes.Count <= 0)
            {
                return new string[] { }
            }
            ;
            var allowZeroNames = new List <string>();

            foreach (var o in nodes)
            {
                if (!(o is XmlElement node))
                {
                    continue;
                }
                var name = node.GetAttribute("name");

                if (string.IsNullOrWhiteSpace(name))
                {
                    continue;
                }
                var allowZeroAttrValue = node.GetAttribute("allow-zero");
                if (string.IsNullOrWhiteSpace(allowZeroAttrValue))
                {
                    continue;
                }
                if (!bool.TryParse(allowZeroAttrValue, out var allowZero))
                {
                    continue;
                }
                if (!allowZero)
                {
                    continue;
                }
                allowZeroNames.Add(name);
            }

            return(allowZeroNames.ToArray());
        }
Example #5
0
        public static string RandomAmericanFirstName(Gender gender, DateTime?dateOfBirth = null)
        {
            var dt = dateOfBirth ?? DateTime.Today.AddYears(-18);

            FirstNamesXml = FirstNamesXml ??
                            XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_FIRST_NAMES, Assembly.GetExecutingAssembly());

            if (FirstNamesXml == null)
            {
                return(gender == Gender.Male ? "John" : "Jane");
            }
            var firstNameNodes = FirstNamesXml.SelectNodes("//first-name");

            if (firstNameNodes == null)
            {
                return(gender == Gender.Male ? "John" : "Jane");
            }
            var decadeElem = FirstNamesXml.SelectSingleNode("//first-name[last()]");

            foreach (var decadeNode in firstNameNodes)
            {
                var decade = decadeNode as XmlElement;
                if (decade == null)
                {
                    continue;
                }
                var start = DateTime.Parse(decade.Attributes["decade-start"].Value);
                var end   = DateTime.Parse(decade.Attributes["decade-end"].Value);

                var cStart = DateTime.Compare(dt, start); //-ge
                var cEnd   = DateTime.Compare(dt, end);   //-le
                if (cStart < 0 || cEnd > 0)
                {
                    continue;
                }

                decadeElem = decade;
                break;
            }
            if (decadeElem == null)
            {
                return(gender == Gender.Male ? "John" : "Jane");
            }
            var genderIdx = gender != Gender.Female ? 0 : 1;
            var mfFnames  = decadeElem.ChildNodes[genderIdx];

            var p = Etx.MyRand.Next(0, mfFnames.ChildNodes.Count);

            return(mfFnames.ChildNodes[p].InnerText);
        }
Example #6
0
        public static string RandomAmericanLastName()
        {
            LastNamesXml = LastNamesXml ??
                           XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_LAST_NAMES, Assembly.GetExecutingAssembly());
            var lnameNodes = LastNamesXml.SelectSingleNode("//last-name");

            if (lnameNodes == null)
            {
                return("Doe");
            }
            var p = Etx.MyRand.Next(0, lnameNodes.ChildNodes.Count);

            return(lnameNodes.ChildNodes[p].InnerText);
        }
Example #7
0
        public static CaCityProvidencePost RandomCanadianCity()
        {
            var ctz = new AddressData();

            CaCityProvidencePost.CaPostCodeXml = CaCityProvidencePost.CaPostCodeXml ??
                                                 XmlDocXrefIdentifier.GetEmbeddedXmlDoc(CaCityProvidencePost.CA_POST_CODE_DATA, Assembly.GetExecutingAssembly());
            if (CaCityProvidencePost.CaPostCodeXml == null)
            {
                return(null);
            }
            var postalCodes = CaCityProvidencePost.CaPostCodeXml.SelectNodes($"//{CaCityProvidencePost.POSTAL_CODE}");
            var dfReturn    = new CaCityProvidencePost(ctz);

            if (postalCodes == null)
            {
                return(dfReturn);
            }

            var pickOne = Etx.MyRand.Next(0, postalCodes.Count);

            var randPostalCode = postalCodes[pickOne] as XmlElement;

            if (randPostalCode == null)
            {
                return(dfReturn);
            }

            var providenceElem = randPostalCode.ParentNode as XmlElement;

            if (providenceElem == null)
            {
                return(dfReturn);
            }

            ctz.RegionAbbrev = providenceElem.GetAttribute(CaCityProvidencePost.ABBREVIATION);
            ctz.RegionName   = providenceElem.GetAttribute(NAME);

            var postalPrefix = randPostalCode.GetAttribute(PREFIX);

            postalPrefix   = String.IsNullOrWhiteSpace(postalPrefix) ? CaCityProvidencePost.DF_FIRST_THREE_CHARS : postalPrefix;
            ctz.PostalCode = $"{postalPrefix} {CaCityProvidencePost.DF_LAST_THREE_CHARS}";

            var municipalityNode = randPostalCode.ChildNodes.OfType <XmlElement>()
                                   .FirstOrDefault(x => x.LocalName == CaCityProvidencePost.MUNICIPALITY && !string.IsNullOrWhiteSpace(x.InnerText));

            ctz.Locality = municipalityNode?.InnerText ?? CaCityProvidencePost.DF_CITY;

            return(new CaCityProvidencePost(ctz));
        }
Example #8
0
        /// <summary>
        /// Returns a hashtable whose keys as American's call Race based on the given <see cref="zipCode"/>
        /// </summary>
        /// <param name="zipCode"></param>
        public static AmericanRacePercents RandomAmericanRaceWithRespectToZip(string zipCode)
        {
            var pick = 0;

            //if calling assembly passed in no-args then return all zeros
            if (String.IsNullOrWhiteSpace(zipCode))
            {
                return(AmericanRacePercents.GetNatlAvg());
            }
            UsZipCodeXml = UsZipCodeXml ??
                           XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_ZIP_CODE_DATA, Assembly.GetExecutingAssembly());
            if (UsZipCodeXml == null)
            {
                return(AmericanRacePercents.GetNatlAvg());
            }
            //get the data for the given zip code
            var zipStatElem = UsZipCodeXml.SelectSingleNode(
                $"//{ZIP_STAT}[@{VALUE}='{zipCode}']");

            if (zipStatElem == null || !zipStatElem.HasChildNodes)
            {
                //try to find on the zip code prefix
                var zip3        = zipCode.Substring(0, 3);
                var zipCodeElem = UsZipCodeXml.SelectSingleNode(
                    $"//{ZIP_CODE_SINGULAR}[@{PREFIX}='{zip3}']");

                if (zipCodeElem == null || !zipCodeElem.HasChildNodes)
                {
                    return(AmericanRacePercents.GetNatlAvg());
                }

                pick = Etx.MyRand.Next(0, zipCodeElem.ChildNodes.Count - 1);

                zipStatElem = zipCodeElem.ChildNodes[pick];
                if (zipStatElem == null || zipStatElem.ChildNodes.Count == 0)
                {
                    return(AmericanRacePercents.GetNatlAvg());
                }
            }

            pick = Etx.MyRand.Next(0, zipStatElem.ChildNodes.Count - 1);
            var arpNode = zipStatElem.ChildNodes[pick];

            return(!TryParseRacePercentsXmlNode(arpNode, out var arp)
                    ? AmericanRacePercents.GetNatlAvg()
                    : arp);
        }
Example #9
0
        public static AmericanUniversity RandomUniversity(string state = null)
        {
            IUniversity univ = null;
            int         pick;

            //pick a univ from the home state
            if (!string.IsNullOrWhiteSpace(state))
            {
                var stateUnivs = GetUniversitiesByState(state);

                if (stateUnivs.Any())
                {
                    pick = Etx.RandomInteger(0, stateUnivs.Length - 1);
                    univ = stateUnivs[pick];
                }
            }

            if (univ == null)
            {
                //pick a university from anywhere in the US
                UnivXml = UnivXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_UNIVERSITY_DATA,
                                                                            Assembly.GetExecutingAssembly());
                var allUnivs = UnivXml?.SelectNodes("//state");
                if (allUnivs == null)
                {
                    return(null);
                }
                pick = Etx.RandomInteger(0, allUnivs.Count - 1);
                if (!(allUnivs[pick] is XmlElement randUnivXml) || !randUnivXml.HasChildNodes)
                {
                    return(null);
                }
                pick = Etx.RandomInteger(0, randUnivXml.ChildNodes.Count - 1);
                if (!(randUnivXml.ChildNodes[pick] is XmlElement univXmlNode))
                {
                    return(null);
                }
                if (TryParseXml(univXmlNode, out var univOut))
                {
                    univ = univOut;
                }
            }
            return((AmericanUniversity)univ);
        }
Example #10
0
        /// <summary>
        /// Gets High Schools based on US State
        /// </summary>
        /// <param name="state">
        /// Gets either a specific states high schools or picks a state at random if missing.
        /// Use either the name or the postal code.
        /// </param>
        /// <returns></returns>
        public static AmericanHighSchool[] GetHighSchoolsByState(string state = null)
        {
            HsXml = HsXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_HIGH_SCHOOL_DATA,
                                                                    Assembly.GetExecutingAssembly());
            if (HsXml == null)
            {
                return new[] { GetDefaultHs() }
            }
            ;
            if (String.IsNullOrWhiteSpace(state))
            {
                _allStateAbbreviations = _allStateAbbreviations ?? GetAllXmlStateAbbreviations(HsXml);

                state = GetRandomStateAbbrev(_allStateAbbreviations);
            }

            //have this deal with if its a postal code or a full name
            var usState = UsState.GetState(state);

            if (usState == null)
            {
                return new[] { GetDefaultHs() }
            }
            ;

            var elements =
                HsXml.SelectNodes($"//state[@name='{usState}']//high-school");

            var parsedList = ParseHighSchoolsFromNodeList(elements);

            foreach (var hs in parsedList)
            {
                hs.StateAbbrev = usState.StateAbbrev;

                hs.StateName = usState.ToString();
            }

            return(parsedList);
        }
Example #11
0
        /// <summary>
        /// Picks a single xml element at random from the US Banks data file
        /// first attempting to match on <see cref="ca"/>, if given.
        /// </summary>
        /// <param name="ca"></param>
        /// <returns></returns>
        internal static XmlElement GetBankXmlElement(CityArea ca)
        {
            UsBanksXml = UsBanksXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_BANKS, Assembly.GetExecutingAssembly());
            if (UsBanksXml == null)
            {
                return(null);
            }
            XmlElement bankXmlElem  = null;
            var        pickFromList = new List <XmlElement>();

            if (!string.IsNullOrWhiteSpace(ca?.City) &&
                !string.IsNullOrWhiteSpace(ca.GetRegionAbbrev()))
            {
                var cityName = UsCityStateZip.FinesseCityName(ca.City);

                var nodes = UsBanksXml.SelectNodes($"//com[@us-state='{ca.GetRegionAbbrev().ToUpper()}']");
                if (nodes != null && nodes.Count > 0)
                {
                    foreach (var node in nodes)
                    {
                        var elem = node as XmlElement;
                        if (elem == null)
                        {
                            continue;
                        }
                        if (!elem.HasAttributes)
                        {
                            continue;
                        }
                        if (elem.GetAttribute("city") != cityName)
                        {
                            continue;
                        }
                        pickFromList.Add(elem);
                    }
                }
            }

            if (!pickFromList.Any())
            {
                var allNodes = UsBanksXml.SelectNodes("//com");
                if (allNodes == null)
                {
                    return(null);
                }
                foreach (var node in allNodes)
                {
                    var elem = node as XmlElement;
                    if (elem == null)
                    {
                        continue;
                    }
                    if (!elem.HasAttributes)
                    {
                        continue;
                    }
                    pickFromList.Add(elem);
                }
            }

            if (pickFromList.Any())
            {
                bankXmlElem = pickFromList[Etx.RandomInteger(0, pickFromList.Count - 1)];
            }
            return(bankXmlElem);
        }
Example #12
0
 /// <summary>
 /// [http://nces.ed.gov/programs/coe/indicator_coi.asp]
 /// </summary>
 /// <returns></returns>
 public static AmericanRacePercents NatlGradRate()
 {
     HsXml = HsXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_HIGH_SCHOOL_DATA,
                                                             Assembly.GetExecutingAssembly());
     return(GetNatlGradRates(HsXml, DF_NATL_AVG));
 }
Example #13
0
        public static UsCityStateZip RandomAmericanCity(string zipCodePrefix = null, bool pickSuburbAtRandom = true)
        {
            const string HAS_HIGH_SCHOOL = "has-high-school";
            const string VALUE           = "value";
            //set defaults
            var ctz = new AddressData
            {
                PostalCode   = $"{UsCityStateZip.DF_ZIPCODE_PREFIX}{Etx.RandomInteger(1, 99):00}",
                RegionAbbrev = UsCityStateZip.DF_STATE_ABBREV
            };

            //pick a zip code prefix at random
            if (String.IsNullOrWhiteSpace(zipCodePrefix))
            {
                zipCodePrefix = UsCityStateZip.RandomAmericanPartialZipCode() ?? UsCityStateZip.DF_ZIPCODE_PREFIX;
            }

            //x-ref it to the zip code data
            var xpathString = $"//{UsCityStateZip.ZIP_CODE_PLURAL}//{UsCityStateZip.ZIP_CODE_SINGULAR}[@{PREFIX}='{zipCodePrefix}']";

            UsCityStateZip.UsZipCodeXml = UsCityStateZip.UsZipCodeXml ??
                                          XmlDocXrefIdentifier.GetEmbeddedXmlDoc(UsCityStateZip.US_ZIP_CODE_DATA, Assembly.GetExecutingAssembly());
            if (UsCityStateZip.UsZipCodeXml == null)
            {
                return(null);
            }
            var randZipCode = UsCityStateZip.UsZipCodeXml.SelectSingleNode(xpathString);

            if (randZipCode?.ParentNode?.Attributes?[NAME] == null)
            {
                ctz.Locality = UsCityStateZip.DF_CITY_NAME;
                return(new UsCityStateZip(ctz));
            }

            //get the containing us state
            ctz.RegionName = randZipCode.ParentNode.Attributes[NAME].Value;
            var nfState = UsState.GetStateByName(ctz.RegionName) ??
                          UsState.GetStateByPostalCode(UsCityStateZip.DF_STATE_ABBREV);

            ctz.RegionAbbrev = nfState.StateAbbrev ?? UsCityStateZip.DF_STATE_ABBREV;
            ctz.SortingCode  = $"{Etx.MyRand.Next(1, 9999):0000}";

            if (!randZipCode.HasChildNodes)
            {
                ctz.PostalCode = $"{zipCodePrefix}{Etx.RandomInteger(1, 99):00}";
            }
            else
            {
                //pick a particular zip-code (ZIP5)
                var zipCodes =
                    randZipCode.ChildNodes.Cast <XmlElement>()
                    .Where(
                        x =>
                        x.Attributes[HAS_HIGH_SCHOOL] != null &&
                        x.Attributes[HAS_HIGH_SCHOOL].Value == Boolean.TrueString)
                    .Select(x => x.Attributes[VALUE].Value).ToArray();
                if (zipCodes.Length <= 0)
                {
                    return(new UsCityStateZip(ctz));
                }
                var pickNum = Etx.RandomInteger(0, zipCodes.Length - 1);
                ctz.PostalCode = zipCodes[pickNum];
            }
            var rr = new UsCityStateZip(ctz);

            rr.SetAddrDataToXmlValues(pickSuburbAtRandom);
            return(rr);
        }
Example #14
0
        /// <summary>
        /// Gets the mean of the factors based on the criteria.
        /// </summary>
        /// <param name="tbl"></param>
        /// <param name="edu"></param>
        /// <param name="race"></param>
        /// <param name="region"></param>
        /// <param name="age"></param>
        /// <param name="gender"></param>
        /// <param name="maritalStatus"></param>
        /// <returns>
        /// A scalar factor above or below the national average(s) based on the given criteria
        /// </returns>
        /// <remarks>
        /// src https://www2.census.gov/programs-surveys/demo/tables/wealth/2013/wealth-asset-ownership/wealth-tables-2013.xlsx
        ///     https://www2.census.gov/programs-surveys/demo/tables/wealth/2011/wealth-asset-ownership/debt-tables-2011.xlsx
        /// </remarks>
        public static double GetFactor(AmericanFactorTables tbl, OccidentalEdu edu, NorthAmericanRace race,
                                       AmericanRegion region, int age, Gender gender, MaritalStatus maritalStatus)
        {
            DebtXml = DebtXml ?? XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_PERSONAL_DEBT,
                                                                        Assembly.GetExecutingAssembly());
            WealthXml = WealthXml ??
                        XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_PERSONAL_WEALTH, Assembly.GetExecutingAssembly());
            var xmlDoc = tbl == AmericanFactorTables.CreditCardDebt || tbl == AmericanFactorTables.HomeDebt ||
                         tbl == AmericanFactorTables.VehicleDebt
                ? DebtXml
                : WealthXml;
            var tblName    = Enum.GetName(typeof(AmericanFactorTables), tbl);
            var eduName    = GetXmlEduName(edu);
            var raceName   = Enum.GetName(typeof(NorthAmericanRace), race);
            var regionName = Enum.GetName(typeof(AmericanRegion), region);
            var genderName = Enum.GetName(typeof(Gender), gender);

            var tblXPath    = $"//table[@name='{tblName}']";
            var factorCount = 0D;
            var sum         = 0.0D;
            var hash        = new Dictionary <string, string>
            {
                { "Edu", eduName },
                { "Race", raceName },
                { "Region", regionName },
            };

            foreach (var factor in hash.Keys)
            {
                var xmlElem =
                    xmlDoc.SelectSingleNode($"{tblXPath}/factor[@name='{factor}']/add[@name='{hash[factor]}']") as
                    XmlElement;
                var factorVal = xmlElem?.Attributes["value"]?.Value;
                if (string.IsNullOrWhiteSpace(factorVal))
                {
                    continue;
                }
                if (double.TryParse(factorVal, out var dblOut))
                {
                    sum         += dblOut;
                    factorCount += 1;
                }
            }

            var ageNode = maritalStatus == MaritalStatus.Married || maritalStatus == MaritalStatus.Remarried
                ? xmlDoc.SelectSingleNode($"{tblXPath}/factor[@name='Age']/factor[@name='Married']")
                : xmlDoc.SelectSingleNode($"{tblXPath}/factor[@name='Age']/factor[@name='{genderName}']");

            factorCount = factorCount <= 0 ? 1 : factorCount;
            if (ageNode == null)
            {
                return(Math.Round(sum / factorCount, 5));
            }
            foreach (var anode in ageNode.ChildNodes)
            {
                var ageElem = anode as XmlElement;
                if (ageElem == null)
                {
                    continue;
                }
                var minAge = ageElem.Attributes["min"]?.Value;
                var maxAge = ageElem.Attributes["max"]?.Value;
                if (string.IsNullOrWhiteSpace(minAge) || string.IsNullOrWhiteSpace(maxAge))
                {
                    continue;
                }
                if (!int.TryParse(minAge, out var min) || !int.TryParse(maxAge, out var max))
                {
                    continue;
                }
                var isInRange = age >= min && age <= max;
                if (!isInRange || string.IsNullOrWhiteSpace(ageElem.Attributes["value"]?.Value))
                {
                    continue;
                }
                var factorVal = ageElem.Attributes["value"].Value;
                if (double.TryParse(factorVal, out var dblOut))
                {
                    sum         += dblOut;
                    factorCount += 1;
                }
            }
            return(Math.Round(sum / factorCount, 5));
        }
Example #15
0
        /// <summary>
        /// Based on the <see cref="ZipCode"/> and <see cref="StateName"/> that are assigned.
        /// </summary>
        /// <returns></returns>
        protected internal XmlNode GetCityXmlNode()
        {
            UsCityXml = UsCityXml ??
                        XmlDocXrefIdentifier.GetEmbeddedXmlDoc(US_CITY_DATA, Assembly.GetExecutingAssembly());
            if (UsCityXml == null)
            {
                return(null);
            }
            string      searchCrit;
            XmlNodeList matchedNodes = null;
            var         data         = GetData();

            //search by city-state
            if (!String.IsNullOrWhiteSpace(data.RegionAbbrev) && !String.IsNullOrWhiteSpace(data.Locality) &&
                UsState.GetStateByPostalCode(data.RegionAbbrev) != null)
            {
                var cityName = FinesseCityName(data.Locality);
                searchCrit =
                    $"//state[@abbreviation='{data.RegionAbbrev}']/city[@name='{cityName.EscapeString(EscapeStringType.XML)}']";
                matchedNodes = UsCityXml.SelectNodes(searchCrit);

                //try again on place names
                if (matchedNodes == null || matchedNodes.Count <= 0)
                {
                    searchCrit =
                        $"//state[@abbreviation='{data.RegionAbbrev}']//place[@name='{cityName.EscapeString(EscapeStringType.XML)}']/..";
                    matchedNodes = UsCityXml.SelectNodes(searchCrit);
                }
            }
            //search by first 3 of Zip Code
            else if (!String.IsNullOrWhiteSpace(data.PostalCode) && data.PostalCode.Length >= 3)
            {
                var zipCodePrefix = data.PostalCode.Substring(0, 3);
                searchCrit   = $"//{ZIP_CODE_SINGULAR}[@{PREFIX}='{zipCodePrefix}']/..";
                matchedNodes = UsCityXml.SelectNodes(searchCrit);
            }

            if (matchedNodes == null || matchedNodes.Count <= 0)
            {
                return(null);
            }
            if (matchedNodes.Count == 1)
            {
                return(matchedNodes[0]);
            }

            //choose one with a msa-code value if possible
            foreach (var matchedNode in matchedNodes)
            {
                var matchedElem = matchedNode as XmlElement;
                if (matchedElem == null)
                {
                    continue;
                }
                if (!matchedElem.HasAttributes)
                {
                    continue;
                }
                var hasMsaCode  = !String.IsNullOrWhiteSpace(matchedElem.GetAttribute(MSA_CODE));
                var hasCbsaCode = !String.IsNullOrWhiteSpace(matchedElem.GetAttribute(CBSA_CODE));
                if (hasCbsaCode || hasMsaCode)
                {
                    return(matchedElem);
                }
            }

            var pick = Etx.RandomInteger(0, matchedNodes.Count - 1);

            return(matchedNodes[pick]);
        }