Чтение вложенного XML в C# без XSLT-файла

У меня есть XML-файл с 3-4 уровнями вложенных детей. Некоторые дети имеют либо отсутствующий элемент, либо дополнительный элемент. Я борюсь с автоматическим чтением XML x children deep и также создаю соответствующие записи с плоскими разделителями, чтобы соответствовать родительскому элементу. Я использую VS 2015 и C# в приложении winform, и конечный результат файла заключается в том, что они записывают структуру, которая должна быть одинаковой для всех элементов, независимо от каких-либо отсутствующих или пустых элементов. Ниже мое событие щелчка кнопки вместе с выборкой данных, с которыми я имею дело. Примечание пункт 1 имеет 1 узел зонирования, пункт 2 имеет 2 узла зонирования и пункт 3 имеет 0 узлов зонирования. Результат отбрасывает мои счетчики столбцов в файле с разделителями, когда я приношу его в EXCEL, например.

        private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            string sDelimiter = "";
            string sNodeName = "";
            string sChildNodeName = "";
            switch (uicmbDelimiter.Text)
            {
                case "TAB":
                    sDelimiter = "t";
                    break;
                case "PIPE":
                    sDelimiter = "|";
                    break;
                case "COMMA":
                    sDelimiter = ",";
                    break;
                default:
                    sDelimiter = ",";
                    break;
            }

            string csvstring = "";
            StreamWriter csv = new StreamWriter(this.uitxtXMLFile.Text + ".out");

            XmlDocument doc = new XmlDocument();
            doc.Load(this.uitxtXMLFile.Text);
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("ab", "http://www.revenue.wi.gov/slf");
            XmlNodeList nodelist = doc.SelectNodes("//ab:Item", nsmgr);
            foreach (XmlNode xnfields in nodelist)
            {
                foreach (XmlNode childnode in xnfields.ChildNodes)
                {
                    if (childnode.ChildNodes.Count > 1)
                    {
                        foreach (XmlNode children in childnode.ChildNodes)
                        {
                            csvstring +=children.LocalName + sDelimiter;
                        }
                    }
                    else
                    {
                        csvstring += childnode.LocalName + sDelimiter;
                    }
                }
                csv.WriteLine(csvstring);
                csvstring = "";
                break;
            }
            csvstring = "";

            foreach (XmlNode xn in nodelist)
            {
                foreach (XmlNode childnode in xn.ChildNodes)
                {
                    if (childnode.ChildNodes.Count > 1)
                    {
                        foreach (XmlNode children in childnode.ChildNodes)
                        {
                            if ((sChildNodeName != children.LocalName) && sChildNodeName !="" )
                            {
                                csvstring += sDelimiter + children.InnerText;
                            }
                            else
                            {
                                csvstring += children.InnerText;
                            }
                            sChildNodeName = children.LocalName;
                        }
                    }
                    else
                    {
                        csvstring += childnode.InnerText;
                    }
                    ///////////
                    ///
                    ///////////
                    if ((sNodeName != childnode.LocalName))
                    {
                        csvstring += sDelimiter;
                    }
                    sNodeName = childnode.LocalName;
                }
                csv.WriteLine(csvstring);
                csvstring = "";
                sNodeName = "";
                sChildNodeName = "";
            }

            csv.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.InnerException.Message);

        }


    }

<?xml version="1.0" encoding="utf-8"?>
<CountyRolls   >
  <Municipality>
    <MunicipalityNumber>002</MunicipalityNumber>
    <Item>
      <RecordNumber>1</RecordNumber>
      <PropertyInfo>
        <LocalID1>1-00001-000</LocalID1>
        <LocalID2>1</LocalID2>
        <Zoning>EXCLUSIVE AGRICULTURE DISTRICT</Zoning>
        <Town>16</Town>
        <Range>05</Range>
        <RangeDirection>W</RangeDirection>
        <Section>01</Section>
        <Quarter40>NE</Quarter40>
        <Quarter160>NE</Quarter160>
        <Legal>FRAC NE1/4 OF NE1/4</Legal>
        <RecordingDocuments>
          <Book>0</Book>
          <Page>0</Page>
          <DocumentNumber>1569517</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>589</Book>
          <Page>204</Page>
          <DocumentNumber>868152</DocumentNumber>
        </RecordingDocuments>
      </PropertyInfo>
      <OwnerAndAddressInfo>
        <MailingAddress>
          <USAddress>
            <AddressLine1>N4929 COUNTY ROAD J</AddressLine1>
            <City>ROCKLAND</City>
            <State>WI</State>
            <ZIPCode>54653</ZIPCode>
          </USAddress>
        </MailingAddress>
        <Owner>
          <Individual>
            <Name>
              <FirstName>DAVID</FirstName>
              <LastName>AXELSEN IRREVOCABLE LIVING TRUST</LastName>
            </Name>
            <Address>
              <USAddress>
                <AddressLine1>N4929 COUNTY ROAD J</AddressLine1>
                <City>ROCKLAND</City>
                <State>WI</State>
                <ZIPCode>54653</ZIPCode>
              </USAddress>
            </Address>
          </Individual>
        </Owner>
        <Owner>
          <Individual>
            <Name>
              <FirstName>RHEA</FirstName>
              <LastName>AXELSEN IRREVOCABLE LIVING TRUST</LastName>
            </Name>
            <Address>
              <USAddress>
                <AddressLine1>N4929 COUNTY ROAD J</AddressLine1>
                <City>ROCKLAND</City>
                <State>WI</State>
                <ZIPCode>54653</ZIPCode>
              </USAddress>
            </Address>
          </Individual>
        </Owner>
        <SiteAddress>
          <AddressLine1>JACKPOT AVE</AddressLine1>
          <City>ROCKLAND</City>
          <State>WI</State>
          <ZIPCode>54653</ZIPCode>
        </SiteAddress>
      </OwnerAndAddressInfo>
      <ValuationInfo>
        <RealProperty>
          <Class4>
            <Acres>8.000</Acres>
            <LandValue>1200</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </Class4>
          <Class5M>
            <Acres>31.460</Acres>
            <LandValue>50300</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </Class5M>
          <ClassTotal>
            <Acres>39.460</Acres>
            <LandValue>51500</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </ClassTotal>
        </RealProperty>
      </ValuationInfo>
      <JurisdictionInfo>
        <County>
          <CountyName>32 La Crosse</CountyName>
          <CountyRate>0.004068228</CountyRate>
          <CountyTax>209.51</CountyTax>
        </County>
        <Municipality>
          <MuniName>Town of Bangor</MuniName>
          <MuniNumber>32002</MuniNumber>
          <MunicipalRate>0.002443039</MunicipalRate>
          <MunicipalTax>125.82</MunicipalTax>
        </Municipality>
        <School>
          <Code>320245</Code>
          <Rate>0.009154910</Rate>
          <Tax>471.48</Tax>
        </School>
        <Tech>
          <Code>000200</Code>
          <Rate>0.001590738</Rate>
          <Tax>81.92</Tax>
        </Tech>
      </JurisdictionInfo>
      <TaxSummary>
        <LandTaxableTotal>51500</LandTaxableTotal>
        <ImprovementsTaxableTotal>0</ImprovementsTaxableTotal>
        <TotalTaxableValue>51500</TotalTaxableValue>
        <EstimatedFairMarketValue>0</EstimatedFairMarketValue>
        <StateTax>8.86</StateTax>
        <OccupationalTax>0</OccupationalTax>
        <ForestTaxable>0</ForestTaxable>
        <BORValue>51500</BORValue>
        <PrivateForestCropTax>0.00</PrivateForestCropTax>
        <ManagedForestLawTax>0.00</ManagedForestLawTax>
        <TaxTotal>897.59</TaxTotal>
        <SchoolCredit>95.43</SchoolCredit>
        <LotteryCredit>0.00</LotteryCredit>
        <FirstDollarCredit>0.00</FirstDollarCredit>
        <SpecialAssessment>
          <SpecialAssessmentDesc>No special charge applies to parcel.</SpecialAssessmentDesc>
          <SpecialAssessmentCharge>0</SpecialAssessmentCharge>
        </SpecialAssessment>
        <DelinquentUtilityCharges>0</DelinquentUtilityCharges>
        <NetTax>897.59</NetTax>
        <Payment>0</Payment>
        <AmountDue>897.59</AmountDue>
        <PriorYearChargebacks>
          <Total>0</Total>
        </PriorYearChargebacks>
        <StateAssessedTelco>0</StateAssessedTelco>
      </TaxSummary>
    </Item>
    <Item>
      <RecordNumber>2</RecordNumber>
      <PropertyInfo>
        <LocalID1>1-00003-001</LocalID1>
        <LocalID2>4</LocalID2>
        <Zoning>CONDITIONAL ZONING            </Zoning>
        <Zoning>EXCLUSIVE AGRICULTURE DISTRICT</Zoning>
        <Town>16</Town>
        <Range>05</Range>
        <RangeDirection>W</RangeDirection>
        <Section>01</Section>
        <Quarter40>NE</Quarter40>
        <Quarter160>SW</Quarter160>
        <Legal>CERTIFIED SURVEY MAP NO. 64 VOL 7 LOT 1 DOC NO. 1159544</Legal>
        <RecordingDocuments>
          <Book>7</Book>
          <Page>64</Page>
          <DocumentNumber>1159544</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>872</Book>
          <Page>36</Page>
          <DocumentNumber>1039008</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1129</Book>
          <Page>264</Page>
          <DocumentNumber>1152228</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1140</Book>
          <Page>558</Page>
          <DocumentNumber>1156940</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1156</Book>
          <Page>31</Page>
          <DocumentNumber>1163596</DocumentNumber>
        </RecordingDocuments>
      </PropertyInfo>
      <OwnerAndAddressInfo>
        <MailingAddress>
          <USAddress>
            <AddressLine1>N4746 COUNTY ROAD J</AddressLine1>
            <City>ROCKLAND</City>
            <State>WI</State>
            <ZIPCode>54653</ZIPCode>
          </USAddress>
        </MailingAddress>
        <Owner>
          <Individual>
            <Name>
              <FirstName>SCOTT R</FirstName>
              <LastName>MILDE</LastName>
            </Name>
            <Address>
              <USAddress>
                <AddressLine1>N4746 COUNTY ROAD J</AddressLine1>
                <City>ROCKLAND</City>
                <State>WI</State>
                <ZIPCode>54653</ZIPCode>
              </USAddress>
            </Address>
          </Individual>
        </Owner>
        <Owner>
          <Individual>
            <Name>
              <FirstName>SUSAN T</FirstName>
              <LastName>MILDE</LastName>
            </Name>
          </Individual>
        </Owner>
        <SiteAddress>
          <AddressLine1>N4746 COUNTY ROAD J</AddressLine1>
          <City>ROCKLAND</City>
          <State>WI</State>
          <ZIPCode>54653</ZIPCode>
        </SiteAddress>
      </OwnerAndAddressInfo>
      <ValuationInfo>
        <RealProperty>
          <Class1>
            <Acres>1.760</Acres>
            <LandValue>13800</LandValue>
            <ImprovementsValue>127400</ImprovementsValue>
          </Class1>
          <ClassTotal>
            <Acres>1.760</Acres>
            <LandValue>13800</LandValue>
            <ImprovementsValue>127400</ImprovementsValue>
          </ClassTotal>
        </RealProperty>
      </ValuationInfo>
      <JurisdictionInfo>
        <County>
          <CountyName>32 La Crosse</CountyName>
          <CountyRate>0.004068228</CountyRate>
          <CountyTax>574.43</CountyTax>
        </County>
        <Municipality>
          <MuniName>Town of Bangor</MuniName>
          <MuniNumber>32002</MuniNumber>
          <MunicipalRate>0.002443039</MunicipalRate>
          <MunicipalTax>344.96</MunicipalTax>
        </Municipality>
        <School>
          <Code>320245</Code>
          <Rate>0.009154910</Rate>
          <Tax>1292.67</Tax>
        </School>
        <Tech>
          <Code>000200</Code>
          <Rate>0.001590738</Rate>
          <Tax>224.61</Tax>
        </Tech>
      </JurisdictionInfo>
      <TaxSummary>
        <LandTaxableTotal>13800</LandTaxableTotal>
        <ImprovementsTaxableTotal>127400</ImprovementsTaxableTotal>
        <TotalTaxableValue>141200</TotalTaxableValue>
        <EstimatedFairMarketValue>143200</EstimatedFairMarketValue>
        <StateTax>24.30</StateTax>
        <OccupationalTax>0</OccupationalTax>
        <ForestTaxable>0</ForestTaxable>
        <BORValue>141200</BORValue>
        <PrivateForestCropTax>0.00</PrivateForestCropTax>
        <ManagedForestLawTax>0.00</ManagedForestLawTax>
        <TaxTotal>2460.97</TaxTotal>
        <SchoolCredit>261.64</SchoolCredit>
        <LotteryCredit>136.65</LotteryCredit>
        <FirstDollarCredit>72.66</FirstDollarCredit>
        <SpecialAssessment>
          <SpecialAssessmentDesc>No special charge applies to parcel.</SpecialAssessmentDesc>
          <SpecialAssessmentCharge>0</SpecialAssessmentCharge>
        </SpecialAssessment>
        <DelinquentUtilityCharges>0</DelinquentUtilityCharges>
        <NetTax>2251.66</NetTax>
        <Payment>0</Payment>
        <AmountDue>2251.66</AmountDue>
        <PriorYearChargebacks>
          <Total>0</Total>
        </PriorYearChargebacks>
        <StateAssessedTelco>0</StateAssessedTelco>
      </TaxSummary>
    </Item>
    <Item>
      <RecordNumber>3</RecordNumber>
      <PropertyInfo>
        <LocalID1>1-00004-000</LocalID1>
        <LocalID2>5</LocalID2>
        <Town>16</Town>
        <Range>05</Range>
        <RangeDirection>W</RangeDirection>
        <Section>01</Section>
        <Quarter40>NE</Quarter40>
        <Quarter160>SE</Quarter160>
        <Legal>SE1/4 FRAC NE1/4</Legal>
        <RecordingDocuments>
          <Book>870</Book>
          <Page>575</Page>
          <DocumentNumber>1038082</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>872</Book>
          <Page>36</Page>
          <DocumentNumber>1039008</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1129</Book>
          <Page>264</Page>
          <DocumentNumber>1152228</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1140</Book>
          <Page>558</Page>
          <DocumentNumber>1156940</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1336</Book>
          <Page>55</Page>
          <DocumentNumber>1234542</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1336</Book>
          <Page>523</Page>
          <DocumentNumber>1234736</DocumentNumber>
        </RecordingDocuments>
        <RecordingDocuments>
          <Book>1385</Book>
          <Page>535</Page>
          <DocumentNumber>1254119</DocumentNumber>
        </RecordingDocuments>
      </PropertyInfo>
      <OwnerAndAddressInfo>
        <MailingAddress>
          <USAddress>
            <AddressLine1>230 21ST ST S</AddressLine1>
            <City>LA CROSSE</City>
            <State>WI</State>
            <ZIPCode>54601</ZIPCode>
          </USAddress>
        </MailingAddress>
        <Owner>
          <Individual>
            <Name>
              <FirstName>GALEN W</FirstName>
              <LastName>PITTMAN</LastName>
            </Name>
            <Address>
              <USAddress>
                <AddressLine1>230 21ST ST S</AddressLine1>
                <City>LA CROSSE</City>
                <State>WI</State>
                <ZIPCode>54601</ZIPCode>
              </USAddress>
            </Address>
          </Individual>
        </Owner>
        <SiteAddress>
          <AddressLine1>COUNTY ROAD J</AddressLine1>
          <City>ROCKLAND</City>
          <State>WI</State>
          <ZIPCode>54653</ZIPCode>
        </SiteAddress>
      </OwnerAndAddressInfo>
      <ValuationInfo>
        <RealProperty>
          <Class5>
            <Acres>9.000</Acres>
            <LandValue>11700</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </Class5>
          <Class6>
            <Acres>31.000</Acres>
            <LandValue>99200</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </Class6>
          <ClassTotal>
            <Acres>40.000</Acres>
            <LandValue>110900</LandValue>
            <ImprovementsValue>0</ImprovementsValue>
          </ClassTotal>
        </RealProperty>
      </ValuationInfo>
      <JurisdictionInfo>
        <County>
          <CountyName>32 La Crosse</CountyName>
          <CountyRate>0.004068228</CountyRate>
          <CountyTax>451.17</CountyTax>
        </County>
        <Municipality>
          <MuniName>Town of Bangor</MuniName>
          <MuniNumber>32002</MuniNumber>
          <MunicipalRate>0.002443039</MunicipalRate>
          <MunicipalTax>270.93</MunicipalTax>
        </Municipality>
        <School>
          <Code>320245</Code>
          <Rate>0.009154910</Rate>
          <Tax>1015.28</Tax>
        </School>
        <Tech>
          <Code>000200</Code>
          <Rate>0.001590738</Rate>
          <Tax>176.41</Tax>
        </Tech>
      </JurisdictionInfo>
      <TaxSummary>
        <LandTaxableTotal>110900</LandTaxableTotal>
        <ImprovementsTaxableTotal>0</ImprovementsTaxableTotal>
        <TotalTaxableValue>110900</TotalTaxableValue>
        <EstimatedFairMarketValue>112500</EstimatedFairMarketValue>
        <StateTax>19.09</StateTax>
        <OccupationalTax>0</OccupationalTax>
        <ForestTaxable>0</ForestTaxable>
        <BORValue>110900</BORValue>
        <PrivateForestCropTax>0.00</PrivateForestCropTax>
        <ManagedForestLawTax>0.00</ManagedForestLawTax>
        <TaxTotal>1932.88</TaxTotal>
        <SchoolCredit>205.50</SchoolCredit>
        <LotteryCredit>0.00</LotteryCredit>
        <FirstDollarCredit>0.00</FirstDollarCredit>
        <SpecialAssessment>
          <SpecialAssessmentDesc>No special charge applies to parcel.</SpecialAssessmentDesc>
          <SpecialAssessmentCharge>0</SpecialAssessmentCharge>
        </SpecialAssessment>
        <DelinquentUtilityCharges>0</DelinquentUtilityCharges>
        <NetTax>1932.88</NetTax>
        <Payment>0</Payment>
        <AmountDue>1932.88</AmountDue>
        <PriorYearChargebacks>
          <Total>0</Total>
        </PriorYearChargebacks>
        <StateAssessedTelco>0</StateAssessedTelco>
      </TaxSummary>
    </Item>
    <Chargebacks>
      <CurrentYear>
        <Total>0</Total>
      </CurrentYear>
    </Chargebacks>
  </Municipality>
</CountyRolls>

2 ответа

  1. xml linq лучше обрабатывает значения null. См. код ниже

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILENAME);
                XElement countyRolls = (XElement)doc.FirstNode;
                XNamespace ns = countyRolls.GetDefaultNamespace();
    
                var results = countyRolls.Elements(ns + "Municipality").Select(x => new {
                    municipalityNumber = (string)x.Element(ns + "MunicipalityNumber"),
                    items = x.Elements(ns + "Item").Select(y => new {
                       recordNumber = (int)y.Element(ns + "RecordNumber"),
                       propertyInfo = y.Elements(ns + "PropertyInfo").Select(z => new {
                          localID1 = (string)z.Element(ns + "LocalID1"),
                          localID2 = (string)z.Element(ns + "LocalID2"),
                          zoning = z.Elements(ns + "Zoning").Select(a => (string)a).ToArray(),
                          town = (string)z.Element(ns + "Town"),
                          range = (string)z.Element(ns + "Range"),
                          rangeDirection = (string)z.Element(ns + "RangeDirection"),
                          section = (string)z.Element(ns + "Section"),
                          quarter40 = (string)z.Element(ns + "Quarter40"),
                          quarter160 = (string)z.Element(ns + "Quarter160"),
                          legal = (string)z.Element(ns + "Legal"),
                          recordingDocuments = z.Elements(ns + "RecordingDocuments").Select(a => new {
                               book = (int)a.Element(ns + "Book"),
                               page = (int)a.Element(ns + "Page"),
                               documentNumber = (int)a.Element(ns + "DocumentNumber")
                          }).ToList()
                       }).FirstOrDefault(),
                       ownerAndAddressInfo = y.Elements(ns + "OwnerAndAddressInfo").Select(z => new { 
                           mailingAddress = z.Descendants(ns + "USAddress").Select(a => new {
                               addressLine1 = (string)a.Element(ns + "AddressLine1"),
                               city = (string)a.Element(ns + "City"),
                               state = (string)a.Element(ns + "State"),
                               zipCode = (string)a.Element(ns + "ZIPCode"),
                           }).FirstOrDefault(),
                           owners = z.Elements(ns + "Owner").Select(a => new {
                               firstName = (string)a.Descendants(ns + "FirstName").FirstOrDefault(),
                               lastName = (string)a.Descendants(ns + "LastName").FirstOrDefault(),
                               addressLine1 = (string)a.Descendants(ns + "AddressLine1").FirstOrDefault(),
                               city = (string)a.Descendants(ns + "City").FirstOrDefault(),
                               state = (string)a.Descendants(ns + "State").FirstOrDefault(),
                               zipCode = (string)a.Descendants(ns + "ZIPCode").FirstOrDefault(),
                           }).ToList(),
                           siteAddress = z.Elements(ns + "SiteAddress").Select(a => new {
                               addressLine1 = (string)a.Descendants(ns + "AddressLine1").FirstOrDefault(),
                               city = (string)a.Descendants(ns + "City").FirstOrDefault(),
                               state = (string)a.Descendants(ns + "State").FirstOrDefault(),
                               zipCode = (string)a.Descendants(ns + "ZIPCode").FirstOrDefault(),
                           }).FirstOrDefault()
                       }).FirstOrDefault(),
                       realProperty = y.Descendants(ns + "RealProperty").Select(z => new {
                           class4 = z.Elements(ns + "Class4").Select(a => new {
                              acres = (decimal)a.Element(ns + "Acres"),
                              landValue = (int)a.Element(ns + "LandValue"),
                              improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                           }).FirstOrDefault(),
                           class5m = z.Elements(ns + "Class5M").Select(a => new {
                              acres = (decimal)a.Element(ns + "Acres"),
                              landValue = (int)a.Element(ns + "LandValue"),
                              improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                           }).FirstOrDefault(),
                           classTotal = z.Elements(ns + "ClassTotal").Select(a => new {
                              acres = (decimal)a.Element(ns + "Acres"),
                              landValue = (int)a.Element(ns + "LandValue"),
                              improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                           }).FirstOrDefault(),
                       }).FirstOrDefault(),
                       jurisdictionInfo = y.Elements(ns + "JurisdictionInfo").Select(z => new {
                           county = z.Elements(ns + "County").Select(a => new {
                               countName = (string)a.Element(ns + "CountyName"),
                               countRate = (string)a.Element(ns + "CountyRate"),
                               countTax = (string)a.Element(ns + "CountyTax")
                           }).FirstOrDefault(),
                           municipality = z.Elements(ns + "Municipality").Select(a => new {
                               muniName = (string)a.Element(ns + "MuniName"),
                               muniNumber = (string)a.Element(ns + "MuniNumber"),
                               municipalRate = (string)a.Element(ns + "MunicipalRate"),
                               municipalTax = (string)a.Element(ns + "MunicipalTax")
                           }).FirstOrDefault(),
                           school = z.Elements(ns + "School").Select(a => new {
                               code = (string)a.Element(ns + "Code"),
                               rate = (string)a.Element(ns + "Rate"),
                               tax = (string)a.Element(ns + "Tax")
                           }).FirstOrDefault(),
                           tech = z.Elements(ns + "Tech").Select(a => new {
                               code = (string)a.Element(ns + "Code"),
                               rate = (string)a.Element(ns + "Rate"),
                               tax = (string)a.Element(ns + "Tax")
                           }).FirstOrDefault()
                       }).FirstOrDefault(),
                       taxSummary = y.Elements(ns + "TaxSummary").Select(z => new {
                           landTaxableTotal = (int)z.Element(ns + "LandTaxableTotal"),
                           improvementsTaxableTotal = (int)z.Element(ns + "ImprovementsTaxableTotal"),
                           totalTaxableValue = (int)z.Element(ns + "TotalTaxableValue"),
                           estimatedFairMarketValue = (int)z.Element(ns + "EstimatedFairMarketValue"),
                           stateTax = (decimal)z.Element(ns + "StateTax"),
                           occupationalTax = (int)z.Element(ns + "OccupationalTax"),
                           forestTaxable = (int)z.Element(ns + "ForestTaxable"),
                           bORValue = (int)z.Element(ns + "BORValue"),
                           privateForestCropTax = (decimal)z.Element(ns + "PrivateForestCropTax"),
                           managedForestLawTax = (decimal)z.Element(ns + "ManagedForestLawTax"),
                           taxTotal = (decimal)z.Element(ns + "TaxTotal"),
                           schoolCredit = (decimal)z.Element(ns + "SchoolCredit"),
                           lotteryCredit = (decimal)z.Element(ns + "LotteryCredit"),
                           firstDollarCredit = (decimal)z.Element(ns + "FirstDollarCredit"),
                           specialAssessmentDesc = (string)z.Descendants(ns + "SpecialAssessmentDesc").FirstOrDefault(),
                           specialAssessmentCharge = (decimal)z.Descendants(ns + "SpecialAssessmentCharge").FirstOrDefault(),
                           delinquentUtilityCharges = (int)z.Element(ns + "DelinquentUtilityCharges"),
                           netTax= (decimal)z.Element(ns + "NetTax"),
                           payment = (decimal)z.Element(ns + "Payment"),
                           amountDue = (decimal)z.Element(ns + "AmountDue")
                       }).FirstOrDefault()
                    }).ToList(),
                    chargebacks = x.Element(ns + "Chargebacks").Descendants(ns + "Total").Select(y => y == null ? 0 : (int)y).FirstOrDefault()
                }).ToList();
            }
        }
    }
    
  2. Ниже приведен пример завершенного рабочего кода:

        private void uicmdLocate_Click(object sender, EventArgs e)
        {
            OpenFileDialog myFile = new OpenFileDialog();
            myFile.Title = "Locate XML File";
            myFile.Filter = "XML Files|*.xml";
            if (myFile.ShowDialog() == DialogResult.OK)
            {
                this.uitxtXMLFile.Text = myFile.FileName;
            }
    
        }
    
    
        private void button3_Click(object sender, EventArgs e)
        {
    
            try
            {
                if (this.uitxtXMLFile.Text == "")
                {
                    throw new Exception("You must select an XML file to convert!");
                }
                string sDelimeter = "";
                string sExtension = "";
                switch (uicmbDelimiter.Text)
                {
                    case "TAB":
                        sDelimeter = "\t";
                        sExtension = ".txt";
                        break;
                    case "PIPE":
                        sDelimeter = "|";
                        sExtension = ".txt";
                        break;
                    case "COMMA":
                        sDelimeter = ",";
                        sExtension = ".csv";
                        break;
                    default:
                        sDelimeter = "\t";
                        sExtension = ".txt";
                        break;
                }
    
                StreamWriter csv = new StreamWriter(this.uitxtXMLFile.Text.Replace(".xml",sExtension));
                string csvstring = "";
                XDocument doc = XDocument.Load(this.uitxtXMLFile.Text);
                XElement countyRolls = (XElement)doc.FirstNode;
                XNamespace ns = countyRolls.GetDefaultNamespace();
    
                var results = countyRolls.Elements(ns + "Municipality").Select(x => new {
                    municipalityNumber = (string)x.Element(ns + "MunicipalityNumber"),
                    items = x.Elements(ns + "Item").Select(y => new {
                        recordNumber = (int)y.Element(ns + "RecordNumber"),
                        propertyInfo = y.Elements(ns + "PropertyInfo").Select(z => new {
                            localID1 = (string)z.Element(ns + "LocalID1"),
                            localID2 = (string)z.Element(ns + "LocalID2"),
                            zoning = z.Elements(ns + "Zoning").Select(a => (string)a).ToArray(),
                            town = (string)z.Element(ns + "Town"),
                            range = (string)z.Element(ns + "Range"),
                            rangeDirection = (string)z.Element(ns + "RangeDirection"),
                            section = (string)z.Element(ns + "Section"),
                            quarter40 = (string)z.Element(ns + "Quarter40"),
                            quarter160 = (string)z.Element(ns + "Quarter160"),
                            legal = (string)z.Element(ns + "Legal"),
                            recordingDocuments = z.Elements(ns + "RecordingDocuments").Select(a => new {
                                book = (int)a.Element(ns + "Book"),
                                page = (int)a.Element(ns + "Page"),
                                documentNumber = (int)a.Element(ns + "DocumentNumber")
                            }).ToList()
                        }).FirstOrDefault(),
                        ownerAndAddressInfo = y.Elements(ns + "OwnerAndAddressInfo").Select(z => new {
                            mailingAddress = z.Descendants(ns + "USAddress").Select(a => new {
                                addressLine1 = (string)a.Element(ns + "AddressLine1"),
                                city = (string)a.Element(ns + "City"),
                                state = (string)a.Element(ns + "State"),
                                zipCode = (string)a.Element(ns + "ZIPCode"),
                            }).FirstOrDefault(),
                            owners = z.Elements(ns + "Owner").Select(a => new {
                                firstName = (string)a.Descendants(ns + "FirstName").FirstOrDefault(),
                                lastName = (string)a.Descendants(ns + "LastName").FirstOrDefault(),
                                businessNameLine1 = (string)a.Descendants(ns + "BusinessNameLine1").FirstOrDefault(),
                                addressLine1 = (string)a.Descendants(ns + "AddressLine1").FirstOrDefault(),
                                city = (string)a.Descendants(ns + "City").FirstOrDefault(),
                                state = (string)a.Descendants(ns + "State").FirstOrDefault(),
                                zipCode = (string)a.Descendants(ns + "ZIPCode").FirstOrDefault(),
                            }).ToList(),
                            siteAddress = z.Elements(ns + "SiteAddress").Select(a => new {
                                addressLine1 = (string)a.Descendants(ns + "AddressLine1").FirstOrDefault(),
                                city = (string)a.Descendants(ns + "City").FirstOrDefault(),
                                state = (string)a.Descendants(ns + "State").FirstOrDefault(),
                                zipCode = (string)a.Descendants(ns + "ZIPCode").FirstOrDefault(),
                            }).FirstOrDefault()
                        }).FirstOrDefault(),
                        realProperty = y.Descendants(ns + "RealProperty").Select(z => new {
                            class4 = z.Elements(ns + "Class4").Select(a => new {
                                acres = (decimal)a.Element(ns + "Acres"),
                                landValue = (int)a.Element(ns + "LandValue"),
                                improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                            }).FirstOrDefault(),
                            class5m = z.Elements(ns + "Class5M").Select(a => new {
                                acres = (decimal)a.Element(ns + "Acres"),
                                landValue = (int)a.Element(ns + "LandValue"),
                                improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                            }).FirstOrDefault(),
                            classTotal = z.Elements(ns + "ClassTotal").Select(a => new {
                                acres = (decimal)a.Element(ns + "Acres"),
                                landValue = (int)a.Element(ns + "LandValue"),
                                improvementsValue = (int)a.Element(ns + "ImprovementsValue")
                            }).FirstOrDefault(),
                        }).FirstOrDefault(),
                        jurisdictionInfo = y.Elements(ns + "JurisdictionInfo").Select(z => new {
                            county = z.Elements(ns + "County").Select(a => new {
                                countName = (string)a.Element(ns + "CountyName"),
                                countRate = (string)a.Element(ns + "CountyRate"),
                                countTax = (string)a.Element(ns + "CountyTax")
                            }).FirstOrDefault(),
                            municipality = z.Elements(ns + "Municipality").Select(a => new {
                                muniName = (string)a.Element(ns + "MuniName"),
                                muniNumber = (string)a.Element(ns + "MuniNumber"),
                                municipalRate = (string)a.Element(ns + "MunicipalRate"),
                                municipalTax = (string)a.Element(ns + "MunicipalTax")
                            }).FirstOrDefault(),
                            school = z.Elements(ns + "School").Select(a => new {
                                code = (string)a.Element(ns + "Code"),
                                rate = (string)a.Element(ns + "Rate"),
                                tax = (string)a.Element(ns + "Tax")
                            }).FirstOrDefault(),
                            tech = z.Elements(ns + "Tech").Select(a => new {
                                code = (string)a.Element(ns + "Code"),
                                rate = (string)a.Element(ns + "Rate"),
                                tax = (string)a.Element(ns + "Tax")
                            }).FirstOrDefault()
                        }).FirstOrDefault(),
                        taxSummary = y.Elements(ns + "TaxSummary").Select(z => new
                        {
                            landTaxableTotal = (int)z.Element(ns + "LandTaxableTotal"),
                            improvementsTaxableTotal = (int)z.Element(ns + "ImprovementsTaxableTotal"),
                            totalTaxableValue = (int)z.Element(ns + "TotalTaxableValue"),
                            estimatedFairMarketValue = (int)z.Element(ns + "EstimatedFairMarketValue"),
                            stateTax = (decimal)z.Element(ns + "StateTax"),
                            occupationalTax = (int)z.Element(ns + "OccupationalTax"),
                            forestTaxable = (int)z.Element(ns + "ForestTaxable"),
                            bORValue = (int)z.Element(ns + "BORValue"),
                            privateForestCropTax = (decimal)z.Element(ns + "PrivateForestCropTax"),
                            managedForestLawTax = (decimal)z.Element(ns + "ManagedForestLawTax"),
                            taxTotal = (decimal)z.Element(ns + "TaxTotal"),
                            schoolCredit = (decimal)z.Element(ns + "SchoolCredit"),
                            lotteryCredit = (decimal)z.Element(ns + "LotteryCredit"),
                            firstDollarCredit = (decimal)z.Element(ns + "FirstDollarCredit"),
                            specialAssessmentDesc = (string)z.Descendants(ns + "SpecialAssessmentDesc").FirstOrDefault(),
                            specialAssessmentCharge = (decimal)z.Descendants(ns + "SpecialAssessmentCharge").FirstOrDefault(),
                            delinquentUtilityCharges = (decimal)z.Element(ns + "DelinquentUtilityCharges"),
                            netTax = (decimal)z.Element(ns + "NetTax"),
                            payment = (decimal)z.Element(ns + "Payment"),
                            amountDue = (decimal)z.Element(ns + "AmountDue"),
                            priorYearChargebacks = (decimal)z.Descendants(ns + "Total").FirstOrDefault(),
                            stateAssessedTelco = (decimal)z.Element(ns + "StateAssessedTelco")
                        }).FirstOrDefault()
                    }).ToList(),
                    chargebacks = x.Element(ns + "Chargebacks").Descendants(ns + "Total").Select(y => y == null ? 0 : (int)y).FirstOrDefault()
                }).ToList();
    
                this.progressBar1.Maximum = results[0].items.Count;
                this.progressBar1.Value = 0;
                this.progressBar1.Step = 1;
    
                csvstring += "recordNumber" + sDelimeter;
                csvstring += "localID1" + sDelimeter;
                csvstring += "localID2" + sDelimeter;
                csvstring += "legal" + sDelimeter;
                csvstring += "addressLine1" + sDelimeter;
                csvstring += "city" + sDelimeter;
                csvstring += "state" + sDelimeter;
                csvstring += "zipCode" + sDelimeter;
                csvstring += "owner" + sDelimeter;
                csvstring += "NameSeq" + sDelimeter;
                csvstring += "BusinessName" + sDelimeter;
                csvstring += "siteaddressLine1" + sDelimeter;
                csvstring += "sitecity" + sDelimeter;
                csvstring += "sitestate" + sDelimeter;
                csvstring += "sitezipCode" + sDelimeter;
                csvstring += "acres" + sDelimeter;
                csvstring += "landValue" + sDelimeter;
                csvstring += "improvementsValue" + sDelimeter;
                csvstring += "landTaxableTotal" + sDelimeter;
                csvstring += "improvementsTaxableTotal" + sDelimeter;
                csvstring += "estimatedFairMarketValue" + sDelimeter;
                csvstring += "stateTax" + sDelimeter;
                csvstring += "occupationalTax" + sDelimeter;
                csvstring += "forestTaxable" + sDelimeter;
                csvstring += "bORValue" + sDelimeter;
                csvstring += "privateForestCropTax" + sDelimeter;
                csvstring += "managedForestLawTax" + sDelimeter;
                csvstring += "taxTotal" + sDelimeter;
                csvstring += "schoolCredit" + sDelimeter;
                csvstring += "lotteryCredit" + sDelimeter;
                csvstring += "firstDollarCredit" + sDelimeter;
                csvstring += "specialAssessmentDesc" + sDelimeter;
                csvstring += "specialAssessmentCharge" + sDelimeter;
                csvstring += "delinquentUtilityCharges" + sDelimeter;
                csvstring += "netTax" + sDelimeter;
                csvstring += "payment" + sDelimeter;
                csvstring += "amountDue" + sDelimeter;
                csvstring += "priorYearChargebacks" + sDelimeter;
                csvstring += "stateAssessedTelco" + sDelimeter;
                csv.WriteLine(csvstring);
                csvstring = "";
    
                for (int i = 0; i < results[0].items.Count; i++)
                {
                    csvstring += results[0].items[i].recordNumber + sDelimeter;
                    // Write Property Info
                    csvstring += results[0].items[i].propertyInfo.localID1 + sDelimeter;
                    csvstring += results[0].items[i].propertyInfo.localID2 + sDelimeter;
                    csvstring += results[0].items[i].propertyInfo.legal + sDelimeter;
                    foreach (string element in results[0].items[i].propertyInfo.zoning)
                    {
                        csvstring += element;
                    }
                    csvstring += "\t";
                    // Write Owner Info
                    if (results[0].items[i].ownerAndAddressInfo.mailingAddress == null)
                    {
                        csvstring += "\t\t\t\t";
                    }
                    else
                    {
                        csvstring += results[0].items[i].ownerAndAddressInfo.mailingAddress.addressLine1 + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.mailingAddress.city + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.mailingAddress.state + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.mailingAddress.zipCode + sDelimeter;
                    }
                    for (int io = 0; io < results[0].items[i].ownerAndAddressInfo.owners.Count; io++)
                    {
                        csvstring += results[0].items[i].ownerAndAddressInfo.owners[io].firstName + " ";
                        csvstring += results[0].items[i].ownerAndAddressInfo.owners[io].lastName + " ";
                    }
                    csvstring += sDelimeter;
                    csvstring += results[0].items[i].ownerAndAddressInfo.owners[0].lastName + " " + results[0].items[i].ownerAndAddressInfo.owners[0].firstName + sDelimeter;
                    csvstring += results[0].items[i].ownerAndAddressInfo.owners[0].businessNameLine1 + sDelimeter;
                    // Site Address
                    if (results[0].items[i].ownerAndAddressInfo.siteAddress == null)
                    {
                        csvstring += "\t\t\t\t";
                    }
                    else
                    {
                        csvstring += results[0].items[i].ownerAndAddressInfo.siteAddress.addressLine1 + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.siteAddress.city + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.siteAddress.state + sDelimeter;
                        csvstring += results[0].items[i].ownerAndAddressInfo.siteAddress.zipCode + sDelimeter;
                    }
                    // Valuation Information
                    csvstring += results[0].items[i].realProperty.classTotal.acres + sDelimeter;
                    csvstring += results[0].items[i].realProperty.classTotal.landValue + sDelimeter;
                    csvstring += results[0].items[i].realProperty.classTotal.improvementsValue + sDelimeter;
                    // Tax Summary Information
                    csvstring += results[0].items[i].taxSummary.landTaxableTotal + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.improvementsTaxableTotal + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.estimatedFairMarketValue + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.stateTax + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.occupationalTax + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.forestTaxable + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.bORValue + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.privateForestCropTax + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.managedForestLawTax + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.taxTotal + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.schoolCredit + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.lotteryCredit + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.firstDollarCredit + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.specialAssessmentDesc + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.specialAssessmentCharge + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.delinquentUtilityCharges + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.netTax + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.payment + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.amountDue + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.priorYearChargebacks + sDelimeter;
                    csvstring += results[0].items[i].taxSummary.stateAssessedTelco + sDelimeter;
                    csv.WriteLine(csvstring);
                    csvstring = "";
                    this.progressBar1.PerformStep();
                    Application.DoEvents();
                }
                csv.Close();
                MessageBox.Show("Complete!", "Done Processing", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                this.progressBar1.Value = 0;
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,"Error Alert",MessageBoxButtons.OK,MessageBoxIcon.Information);
            }
        }
    
    }
    

    }