簡體   English   中英

C#XML節點缺少元素 - 嘗試保存為CSV

[英]C# XML nodes missing elements - Trying to save as CSV

我發現很多關於將XML保存為CSV的帖子,但我的問題是我的XML中的某些節點比其他節點的元素少。 這導致我的CSV列關閉,這不是很有幫助。 我正在使用的XML數據來自第三方API。

這是我的代碼:

    internal static void XmlToCsvFile(XmlDocument doc, string fileName)
    {
        var xml = new XDocument();
        xml = XDocument.Parse(doc.InnerXml);

        StringBuilder sb = new StringBuilder(100000);

        var xmlDocForHeaders = new XmlDocument();
        xmlDocForHeaders.InnerXml = xml.Root.FirstNode.ToString();

        var xdocForHeaders = XDocument.Parse(xmlDocForHeaders.InnerXml);

        foreach (var element in xdocForHeaders.Elements().Elements())
        {
            sb.Append($"{element.Name},");
        }

        sb.Append("\n");

        foreach (XElement node in xml.Descendants("Table"))
        {
            foreach (XElement innerNode in node.Elements())
            {
                foreach (XElement elements in innerNode.Elements())
                {
                    sb.Append($"\"{elements.Value}\",");
                }

                sb.Append("\n");
            }

            sb.Remove(sb.Length - 1, 1);
            sb.AppendLine();
        }

        var csvOut = sb.ToString();
        SaveDataToCsvFile(csvOut);
    }

我知道我不需要將我的XmlDocument轉換為XDocument,但這在當時看起來更容易。

任何幫助將不勝感激!

謝謝!

編輯:

以下是XML數據的示例:

<Table>
  <Record>
    <StoreID>43</StoreID>
    <StoreName>30455 Juniper</StoreName>
    <Disabled>0</Disabled>
    <Abbreviation>UC30455</Abbreviation>
    <ManagerEmployeeID>297</ManagerEmployeeID>
    <ManagerCommissionable>false</ManagerCommissionable>
    <Address>400 Green St.</Address>
    <City>Juniper</City>
    <StateProv>WA</StateProv>
    <ZipPostal>47895</ZipPostal>
    <Country>United States</Country>
    <PhoneNumber>8056954823</PhoneNumber>
    <FaxNumber>5085236524</FaxNumber>
    <DistrictNameJuniper South</DistrictName>
    <RegionName>High Hills Region</RegionName>
    <ChannelName>West Market</ChannelName>
    <StoreType>1/2 Tier-PP</StoreType>
    <GLCode>5862</GLCode>
    <SquareFootage>1100</SquareFootage>
    <LocationCode>MX029</LocationCode>
    <Latitude>49.5236458952</Latitude>
    <Longitude>-192.532150000</Longitude>
    <AddressVerified>Not Verified</AddressVerified>
    <TimeZone>(GMT-08:00) West Time (US &amp; Canada)</TimeZone>
    <AdjustDST>true</AdjustDST>
    <CashPolicy>Single-Drawer</CashPolicy>
    <MaxCashDrawer>0.0000</MaxCashDrawer>
    <Serial_on_OE>false</Serial_on_OE>
    <Phone_on_OE>true</Phone_on_OE>
    <PAW_on_OE>true</PAW_on_OE>
    <Comment_on_OE>false</Comment_on_OE>
    <HideCustomerAddress>false</HideCustomerAddress>
    <EmailAddress>donotreply@email.com</EmailAddress>
    <GeneralLocationNotes>Mon-Sat 9am-8pm, Sun 12pm-5pm</GeneralLocationNotes>
    <SaleInvoiceComment />
    <BankDetails />
    <Taxes>UT - Sales Tax 6.6%, 1.9% E911 Fee (WA)</Taxes>
    <Rent>0.0000</Rent>
    <PropertyTaxes>0.0000</PropertyTaxes>
    <InsuranceAmount>0.0000</InsuranceAmount>
    <OtherCharges>0.0000</OtherCharges>
    <DepositTaken>0.0000</DepositTaken>
    <LeaseNotes />
    <InsuranceCompany />
    <LandlordNotes />
    <LandlordName>COMPANY-JUNIPER/60144582</LandlordName>
    <UseLocationEmail>true</UseLocationEmail>
    <LocationEntityID>25367</LocationEntityID>
  </Record>
  <Record>
    <StoreID>107</StoreID>
    <StoreName>9589 CLC Go Company.com</StoreName>
    <Disabled>0</Disabled>
    <Abbreviation>CL9589</Abbreviation>
    <ManagerEmployeeID>853</ManagerEmployeeID>
    <ManagerCommissionable>false</ManagerCommissionable>
    <Address>9852 Bland Banks Blvd.</Address>
    <City>Honneyton</City>
    <StateProv>MI</StateProv>
    <ZipPostal>69421</ZipPostal>
    <Country>USA</Country>
    <PhoneNumber>9595525214</PhoneNumber>
    <FaxNumber>3625485236</FaxNumber>
    <DistrictName>Recovery Services</DistrictName>
    <RegionName>zRetail Support</RegionName>
    <ChannelName>zRetail Support</ChannelName>
    <StoreType>Care Center</StoreType>
    <GLCode>0356</GLCode>
    <SquareFootage>2163</SquareFootage>
    <AddressVerified>Not Verified</AddressVerified>
    <TimeZone>(GMT-07:00) Central Time (US &amp; Canada)</TimeZone>
    <AdjustDST>true</AdjustDST>
    <CashPolicy>Single-Drawer</CashPolicy>
    <MaxCashDrawer>0.0000</MaxCashDrawer>
    <Serial_on_OE>false</Serial_on_OE>
    <Phone_on_OE>true</Phone_on_OE>
    <PAW_on_OE>false</PAW_on_OE>
    <Comment_on_OE>false</Comment_on_OE>
    <HideCustomerAddress>false</HideCustomerAddress>
    <EmailAddress>donotreply@email.com</EmailAddress>
    <GeneralLocationNotes />
    <SaleInvoiceComment />
    <BankDetails />
    <Taxes>MI - Honneyton</Taxes>
    <Rent>0.0000</Rent>
    <PropertyTaxes>0.0000</PropertyTaxes>
    <InsuranceAmount>0.0000</InsuranceAmount>
    <OtherCharges>0.0000</OtherCharges>
    <DepositTaken>0.0000</DepositTaken>
    <LeaseNotes />
    <InsuranceCompany />
    <LandlordNotes />
    <LandlordName />
    <UseLocationEmail>true</UseLocationEmail>
    <LocationEntityID>25397</LocationEntityID>
  </Record>
</Table>

如您所見,第一個記錄包含lat和long元素,但第二個記錄不包含lat和long元素。 這會在轉換為CSV時拋棄所有內容。

再次感謝!

編輯:

基於你所有的好評,這里最終為我工作了!

internal static string XmlToCsvFile(XmlDocument doc, string fileName)
{
    var xml = XDocument.Parse(doc.InnerXml);

    var sb = new StringBuilder();

    var record = new Dictionary<string, string>();

    foreach (var element in xml.Descendants("Record").Elements())
    {
        if (!record.ContainsKey(element.Name.ToString()))
        {
            record.Add(element.Name.ToString(), "");
        }
    }

    foreach (var key in record.Keys)
    {
        sb.Append($"{key},");
    }

    sb.Remove(sb.Length - 1, 1);
    sb.AppendLine();

    foreach (var node in xml.Descendants("Record"))
    {
        foreach (var key in record.Keys.ToList())
        {
            record[key] = "";
        }

        foreach (var elements in node.Elements())
        {
            record[elements.Name.ToString()] = elements.Value.ToString();
        }

        foreach (var value in record.Values)
        {
            sb.Append($"\"{value}\",");
        }

        sb.Remove(sb.Length - 1, 1);
        sb.AppendLine();
    }

    var csvOut = sb.ToString();
    SaveDataToCsvFile(csvOut);

    return csvOut;
}

這是我在評論中所說的內容的快速說明。 由於您似乎只是一次性執行此操作,因此您可以將XML解析為匿名類型的集合,然后遍歷該集合以寫出CSV。

簡單的例子:

var records = xml.Descedants("Record").Select(r => new
              {
                  StoreID = (string)r.Element("StoreID"),
                  StoreName = (string)r.Element("StoreName"),
                  // other elements
              };

注意顯式轉換為字符串 - 如果元素丟失,這將返回null,這將解決某些記錄中優雅地缺少某些元素的問題。 否則你將不得不寫一堆額外的代碼來檢查缺少的元素,這將變得非常難看。

一旦你收集了匿名類型,你就可以遍歷它們來寫出CSV:

foreach(var record in records)
{
    // Here you can access the individual properties in the currently selected record
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM