2017-01-12 8 views
0

XMLをCSV形式で保存すると多くの投稿が見つかりましたが、XMLの一部のノードには他の要素よりも要素が少なくなっています。これは私のCSV列をオフにしていますが、あまり役に立ちません。私が使用しているXMLデータは、サードパーティのAPIから来ています。XMLノードに要素がありません - CSVとして保存しよう

は、ここに私のコードです:私はXDocumentに私のXmlDocumentオブジェクトを変換する必要はありません知っている

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); 
    } 

が、これは一度に簡単に見えました。

ご協力いただければ幸いです!

ありがとうございます!

編集:ここでは

は、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>[email protected]</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>[email protected]</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> 

、最初のレコードは、緯度と長い要素が含まれていますが、2番目にはありません。これは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; 
} 
+2

あなたがサンプルXMLを提供することはできますか? –

+0

データを保持するクラスを作成し、LINQ to XML経由でXMLを解析して欠落した要素を適切に処理し、クラスのコレクションをCSV形式で出力するのはなぜですか? – Tim

+0

また、匿名のタイプにしてからCSVファイルに処理することもできます。 – Tim

答えて

0

ここに私のコメントで述べたことの簡単な説明があります。あなたはワンショットでこれをやっているように見えるので、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 
} 
+0

ありがとう!あなたの答えは正しい軌道に乗っていますが、入ってくるデータに応じてキーを動的に作成する必要があるので(CSVヘッダーが動的になるように)、辞書を使ってデータをどのように見えるかを定義しました私のノードキーの新しいキーを追加してください。次に、各ノードの辞書に自分のデータを追加することができます。これはうまくいくように見えましたが、必要以上に扱いにくいかもしれません。それを掃除するための提案は非常に高く評価されます!上の私の編集を見てください。あなたのご親切に感謝します!! – David

関連する問題