为元素节点解析 XML 文件,然后将文本存储在不同的数组中以加载到 Excel

Parsing XML file for element nodes then storing text in different arrays for loading into Excel

我想解析我将从亚马逊收到的 XML 文件,然后获取数据并将其输入 Excel 中的自定义发票并打印。

我已经完成了这项任务的大部分,但是当客户的地址部分有 2 个部分(例如 <AdressLine1><AddressLine2> 时,我 运行 遇到了困难字段,然后我的两个数组不相等,当我尝试将值写入 excel 单元格时,它会在 excel_create 中的循环中引发错误。

这是我的示例 XML 文件:

<ListOrdersResponse xmlns="https://mws.amazonservices.com/Orders/2013-09-01">
<ListOrdersResult>
    <NextToken>M1JyahCtnbyaJqJYLDm0ZIfVkJJPpovR78ndw9jqj1Q/69u0e9w5/rQzazHyYVyLqBXdLk4iogxpJASl2BeRe8j0Nx3CIFZQQMZu4ky1kPOeXaRUvtI0tSJ0wMvlylZkWQWPqGlbsnPaEpJjLWtrc+QJ10Z22+qvY/7NeGX36M2lPNv+vCtnKbuZIF9n45mtnrZ4AbBdBTfK25ICwjklgZC1Ikmk90PCwrOwRyEF9TC5HmwX5IAmwKfxnqm3JqvZfwylPI5qZH51NMrpM18PB5GesRwkZOQCT2ijH+OaBgLthhfBGj6DwqJZsZEQ+rF525news0zC1z2PvV1ggto2Jcae56fKGloAreSIoDY6+Vu4dey78hEtutyjMqWzuEhtk8n/YPwqr6cgigTv6iG1zzBuIzaoIZ5Q2QZkesSbBJRVhUbQn8uebbKT14gSEgJXREjaOhXHEOu88CBt+gncOCR1k9eFxFwh3b1o15VFoq4DX+xmmNRmA==</NextToken>
    <CreatedBefore>06/27/2015 00:00:00</CreatedBefore>
    <Orders>
        <Order>
            <AmazonOrderId>102-0657116-1777031</AmazonOrderId>
            <PurchaseDate>06/25/2015 19:48:25</PurchaseDate>
            <LastUpdateDate>06/25/2015 20:18:42</LastUpdateDate>
            <OrderStatus>Unshipped</OrderStatus>
            <FulfillmentChannel>MFN</FulfillmentChannel>
            <SalesChannel>Amazon.com</SalesChannel>
            <ShipServiceLevel>Std Cont US Street Addr</ShipServiceLevel>
            <ShippingAddress>
                <Name>dan hendricks</Name>
                <AddressLine1>THE BOTIQUE &amp;amp; TAPES</AddressLine1>
                <AddressLine2>330 MAIN ST</AddressLine2>
                <City>LUBBOCK</City>
                <StateOrRegion>TX</StateOrRegion>
                <PostalCode>07345-1742</PostalCode>
                <CountryCode>US</CountryCode>
                <Phone>2738953644</Phone>
            </ShippingAddress>
            <OrderTotal>
                <CurrencyCode>USD</CurrencyCode>
                <Amount>52.00</Amount>
            </OrderTotal>
            <NumberOfItemsShipped>0</NumberOfItemsShipped>
            <NumberOfItemsUnshipped>1</NumberOfItemsUnshipped>
            <PaymentExecutionDetail />
            <PaymentMethod>Other</PaymentMethod>
            <MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
            <BuyerEmail>ted101@marketplace.amazon.com</BuyerEmail>
            <BuyerName>dan hendricks</BuyerName>
            <ShipmentServiceLevelCategory>Standard</ShipmentServiceLevelCategory>
            <ShippedByAmazonTFM>False</ShippedByAmazonTFM>
            <OrderType>StandardOrder</OrderType>
            <EarliestShipDate>06/26/2015 02:00:00</EarliestShipDate>
            <LatestShipDate>06/30/2015 01:59:59</LatestShipDate>
            <EarliestDeliveryDate>07/01/2015 02:00:00</EarliestDeliveryDate>
            <LatestDeliveryDate>07/08/2015 01:59:59</LatestDeliveryDate>
            <IsBusinessOrder>False</IsBusinessOrder>
            <IsPrime>False</IsPrime>
            <IsPremiumOrder>False</IsPremiumOrder>
        </Order>
        <Order>
            <AmazonOrderId>103-6846365-0842605</AmazonOrderId>
            <PurchaseDate>06/26/2015 11:06:16</PurchaseDate>
            <LastUpdateDate>06/26/2015 11:36:33</LastUpdateDate>
            <OrderStatus>Unshipped</OrderStatus>
            <FulfillmentChannel>MFN</FulfillmentChannel>
            <SalesChannel>Amazon.com</SalesChannel>
            <ShipServiceLevel>Std Cont US Street Addr</ShipServiceLevel>
            <ShippingAddress>
                <Name>bob dylan</Name>
                <AddressLine1>130 CHERRY LANE</AddressLine1>
                <City>MIAMI</City>
                <StateOrRegion>FLORIDA</StateOrRegion>
                <PostalCode>83420-9595</PostalCode>
                <CountryCode>US</CountryCode>
                <Phone>3076595976</Phone>
            </ShippingAddress>
            <OrderTotal>
                <CurrencyCode>USD</CurrencyCode>
                <Amount>43.00</Amount>
            </OrderTotal>
            <NumberOfItemsShipped>0</NumberOfItemsShipped>
            <NumberOfItemsUnshipped>1</NumberOfItemsUnshipped>
            <PaymentExecutionDetail />
            <PaymentMethod>Other</PaymentMethod>
            <MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
            <BuyerEmail>jfkdkl@marketplace.amazon.com</BuyerEmail>
            <BuyerName>Matt dylan</BuyerName>
            <ShipmentServiceLevelCategory>Standard</ShipmentServiceLevelCategory>
            <ShippedByAmazonTFM>False</ShippedByAmazonTFM>
            <OrderType>StandardOrder</OrderType>
            <EarliestShipDate>06/29/2015 02:00:00</EarliestShipDate>
            <LatestShipDate>07/01/2015 01:59:59</LatestShipDate>
            <EarliestDeliveryDate>07/02/2015 02:00:00</EarliestDeliveryDate>
            <LatestDeliveryDate>07/09/2015 01:59:59</LatestDeliveryDate>
            <IsBusinessOrder>False</IsBusinessOrder>
            <IsPrime>False</IsPrime>
            <IsPremiumOrder>False</IsPremiumOrder>
        </Order>
        <Order>
            <AmazonOrderId>109-5667692-9305063</AmazonOrderId>
            <PurchaseDate>06/26/2015 15:33:15</PurchaseDate>
            <LastUpdateDate>06/26/2015 16:03:34</LastUpdateDate>
            <OrderStatus>Unshipped</OrderStatus>
            <FulfillmentChannel>MFN</FulfillmentChannel>
            <SalesChannel>Amazon.com</SalesChannel>
            <ShipServiceLevel>Std Cont US Street Addr</ShipServiceLevel>
            <ShippingAddress>
                <Name>susie orman</Name>
                <AddressLine1>2452 POEF CREEK RD</AddressLine1>
                <City>NEW YORK</City>
                <StateOrRegion>NY</StateOrRegion>
                <PostalCode>28538-8554</PostalCode>
                <CountryCode>US</CountryCode>
                <Phone>8782827332</Phone>
            </ShippingAddress>
            <OrderTotal>
                <CurrencyCode>USD</CurrencyCode>
                <Amount>135.00</Amount>
            </OrderTotal>
            <NumberOfItemsShipped>0</NumberOfItemsShipped>
            <NumberOfItemsUnshipped>1</NumberOfItemsUnshipped>
            <PaymentExecutionDetail />
            <PaymentMethod>Other</PaymentMethod>
            <MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
            <BuyerEmail>sdafgeg@marketplace.amazon.com</BuyerEmail>
            <BuyerName>Susie orman</BuyerName>
            <ShipmentServiceLevelCategory>Standard</ShipmentServiceLevelCategory>
            <ShippedByAmazonTFM>False</ShippedByAmazonTFM>
            <OrderType>StandardOrder</OrderType>
            <EarliestShipDate>06/29/2015 02:00:00</EarliestShipDate>
            <LatestShipDate>07/01/2015 01:59:59</LatestShipDate>
            <EarliestDeliveryDate>07/02/2015 02:00:00</EarliestDeliveryDate>
            <LatestDeliveryDate>07/09/2015 01:59:59</LatestDeliveryDate>
            <IsBusinessOrder>False</IsBusinessOrder>
            <IsPrime>False</IsPrime>
            <IsPremiumOrder>False</IsPremiumOrder>
        </Order>
    </Orders>
</ListOrdersResult>
<ResponseMetadata>
    <RequestId>519992f0-701c-4211-9f3d-3c73b520c626</RequestId>
</ResponseMetadata>

那么这是我解析它并将其存储在我的 excel 文件中的代码:

using System;
using System.IO;
using System.Xml;
using Excel = Microsoft.Office.Interop.Excel;
using System.Linq;
using System.Xml.Linq;
using System.Collections;
using System.Collections.Generic;


class Program
{
    static void Main()
    {
        Parse p = new Parse();
        file_create f = new file_create();

        ArrayList collection = p.Names("Name");
        ArrayList collection2 = p.Names("AddressLine1");
        ArrayList collection3 = p.Names("AddressLine2");
        ArrayList collection4 = p.Names("City");
        ArrayList collection5 = p.Names("StateOrRegion");

        string[] myArray = (string[])collection.ToArray(typeof(string));
        string[] myArray2 = (string[])collection2.ToArray(typeof(string));
        string[] myArray3 = (string[])collection3.ToArray(typeof(string));
        string[] myArray4 = (string[])collection4.ToArray(typeof(string));
        string[] myArray5 = (string[])collection5.ToArray(typeof(string));

        for (int i = 0; i < myArray.Length; i++)
        {
            myArray[i] = myArray[i].ToUpper();
        }

    /*    foreach(string i in myArray)
        {
           int count = 0;
           count++;        
           Console.WriteLine("Name " + count + " is: " + i);
        }

        foreach (string i in myArray2)
        {
            int count = 0;
            count++;
            Console.WriteLine("Name " + count + " is: " + i);
        }
*/
        int count = 0;
        foreach (string i in myArray3)
        {
            count++;
            Console.WriteLine("Name " + count + " is: " + i);
        }
        Console.ReadLine();

        f.Excel_Create(myArray, myArray2, myArray3, myArray4, myArray5);

        //  string uppername = name.ToUpper();
        //  f.Excel_Create(uppername);

    }

    public class Parse
    {
      public ArrayList Names(string a)
        { 
            var filepath = Path.Combine(Directory.GetCurrentDirectory(), "Perls.xml");
        XmlDocument xmlDoc = new XmlDocument();
        ArrayList collection = new ArrayList();
        ArrayList adcollection = new ArrayList();


        if (File.Exists(filepath))
        {
            xmlDoc.Load(filepath);

            switch (a)
            {
                case "Name":

                    XmlNodeList names = xmlDoc.GetElementsByTagName("Name");

                    foreach (XmlNode node in names)
                    {
                        XmlElement namesElement = (XmlElement)node;

                        collection.Add(namesElement.InnerText);
                    }
                    break;
                case "AddressLine1":

                    XmlNodeList addressline1 = xmlDoc.GetElementsByTagName("AddressLine1");

                    foreach (XmlNode node in addressline1)
                    {
                        XmlElement namesElement = (XmlElement)node;

                        collection.Add(namesElement.InnerText);
                    }
                    break;

                case "AddressLine2":

                    XmlNodeList addressline2 = xmlDoc.GetElementsByTagName("AddressLine2");

                    foreach (XmlNode node in addressline2)
                    {
                        XmlElement namesElement = (XmlElement)node;

                        collection.Add(namesElement.InnerText);
                    }
                    break;

                case "City":

                    XmlNodeList City = xmlDoc.GetElementsByTagName("City");

                    foreach (XmlNode node in City)
                    {
                        XmlElement namesElement = (XmlElement)node;

                        collection.Add(namesElement.InnerText);
                    }
                    break;

                case "StateOrRegion":

                    XmlNodeList State = xmlDoc.GetElementsByTagName("StateOrRegion");

                    foreach (XmlNode node in State)
                    {
                        XmlElement namesElement = (XmlElement)node;

                        collection.Add(namesElement.InnerText);
                    }

                    break;                   
            }

        }
        return collection;
     }
  }

    public class file_create
    {
        public void Excel_Create(string[] a, string[] b, string[] c, string[] d, string[] e)
        {
            var mySheet = Path.Combine(Directory.GetCurrentDirectory(), "Isopropanol - Tech Grade.xlsx");
            Excel.Application xlApp = new Excel.Application();
            xlApp.Visible = true;


            if (xlApp == null)
            {
                Console.WriteLine("Excel is not properly installed!!");
                return;
            }

            try
            {
                Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(mySheet);
                Excel.Sheets xlSheets = xlWorkbook.Worksheets;

                string currentSheet = "Invoice";
                Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlSheets.get_Item(currentSheet);

                int num = 10106;

                for (int i = 0; i < a.Length; i++)
                {
                    Excel.Range invoicenum = (Excel.Range)xlWorksheet.get_Range("NO", "NO");
                    invoicenum.Value2 = "M" + num;

                    num++;

                    Excel.Range xlCell = (Excel.Range)xlWorksheet.get_Range("data5", "data5");
                    xlCell.Value2 = a[i];
                    Excel.Range xlCell2 = (Excel.Range)xlWorksheet.get_Range("E13", "E13");
                    xlCell2.Value2 = b[i];
                    if(c[i] != null)
                    {
                        Excel.Range xlCell3 = (Excel.Range)xlWorksheet.get_Range("E14", "E14");
                        xlCell3.Value2 = c[i];

                        Excel.Range xlCell4 = (Excel.Range)xlWorksheet.get_Range("E15", "E15");
                        xlCell4.Value2 = d[i] + ", " + e[i];
                    }

                }
                xlWorksheet.PrintOutEx();

            }
            catch (Exception ex)
            {
                xlApp.Quit();

            }
        }
    }
}

if(c[i] != null) 每当此测试失败时,我都会收到错误消息。我相信这是因为当我存储 AddressLine2 节点时,它不会创建与我的其余数组大小相同的数组,因为只有一个客户有第二个地址。

无论如何,我们将不胜感激。

更新代码:

using System;
using System.IO;
using System.Xml;
using Excel = Microsoft.Office.Interop.Excel;
using System.Linq;
using System.Xml.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;


class Program
{
    static void Main()
    {

        var path = Path.Combine(Directory.GetCurrentDirectory(), "perls.xml");

        var file = XDocument.Load(path);

        string xml = file.ToString();

        var doc = XDocument.Parse(xml);

        var addresses = Addresses(doc);

        WritetoExcel(addresses);
    }


        private static IEnumerable<Address> Addresses(XContainer doc)
    {
        XNamespace ns = "https://mws.amazonservices.com/Orders/2013-09-01";

        return from address in doc.Descendants(ns + "ShippingAddress")
               select new Address
               {
                   Name = (string) address.Element(ns + "Name"),
                   AddressLine1 = (string) address.Element(ns + "AddressLine1"),
                   AddressLine2 = (string) address.Element(ns + "AddressLine2"),
                   City = (string) address.Element(ns + "City"),
                   State = (string) address.Element(ns + "StateOrRegion")
               };
    }

        private static void WritetoExcel(IEnumerable<Address> addresses)
        {
            var mySheet = Path.Combine(Directory.GetCurrentDirectory(), "Isopropanol - Tech Grade.xlsx");
            Excel.Application xlApp = new Excel.Application();
            xlApp.Visible = true;


            if (xlApp == null)
            {
                Console.WriteLine("Excel is not properly installed!!");
                return;
            }

            try
            {
                Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(mySheet);
                Excel.Sheets xlSheets = xlWorkbook.Worksheets;

                string currentSheet = "Invoice";
                Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlSheets.get_Item(currentSheet);

                int num = 10106;

                foreach(var address in addresses)
                {

                    Excel.Range invoicenum = (Excel.Range)xlWorksheet.get_Range("NO", "NO");
                    invoicenum.Value2 = "M" + num;

                    num++;

                    Excel.Range xlCell = (Excel.Range)xlWorksheet.get_Range("data5", "data5");
                  //  Excel.Range c_xlCell = (Excel.Range)xlWorksheet.get_Range("");
                    xlCell.Value2 = address.Name.ToUpper();
                   // xlCell.Copy();


                    Excel.Range xlCell2 = (Excel.Range)xlWorksheet.get_Range("E13", "E13");
                    string a = WebUtility.HtmlDecode(address.AddressLine1);
                    xlCell2.Value2 = a;

                    Excel.Range xlCell3 = (Excel.Range)xlWorksheet.get_Range("E14", "E14");
                    Excel.Range xlCell4 = (Excel.Range)xlWorksheet.get_Range("E15", "E15");

                    if (address.AddressLine2 != null)
                    {

                        xlCell3.Value2 = address.AddressLine2;
                        xlCell4.Value2 = address.City + ", " + address.State;

                    }

                    else
                    {
                        xlCell3.Value2 = address.City + ", " + address.State;
                        xlCell4.Value2 = "";
                    }

                    Excel.Range sourceRange = (Excel.Range)xlWorksheet.get_Range("data5", "E15");
                    Excel.Range destinationRange = (Excel.Range)xlWorksheet.get_Range("J12", "J15");

                    sourceRange.Copy(Type.Missing);
                    destinationRange.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteValuesAndNumberFormats, Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
                }


                GC.Collect();
                GC.WaitForPendingFinalizers();

                Marshal.FinalReleaseComObject(xlSheets);
                Marshal.FinalReleaseComObject(xlWorksheet);


                xlWorkbook.SaveAs("Isopropanol - Tech Grade.xlsx", Excel.XlFileFormat.xlWorkbookDefault);
                xlWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
                Marshal.FinalReleaseComObject(xlWorkbook);

                xlApp.Quit();
                Marshal.FinalReleaseComObject(xlApp);

// xlWorksheet.PrintOutEx();
            }
            catch (Exception ex)
            {
                xlApp.Quit();

            }         
        }
    }

    public class Address
    {
        public string Name { get; set; }
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
    }

您是对的,AddressLine2 是您的问题,因为只有您的一个客户有第二个地址行。您需要确保 return 每个不包含此元素的地址都有一个空行(否则您将不知道哪个 AddressLine2 与哪个地址相关) - 这不是很简单您如何阅读 XML.

以这种方式编写代码容易出现此类错误,并且某些命名会影响可读性。例如,将您的 collections/arrays 命名为 collection1collection2abc 意味着您必须不断上下滚动以查看弄清楚它们实际代表什么。

将它们命名为 namescities 等将是一种改进,但更好的是,为什么不创建一个 Address class?

public class Address
{
    public string Name { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string StateOrRegion { get; set; }    
}

然后,不用在 Parse 中使用大量 copy/paste 代码,只需使用 LINQ to XML 来创建您的 Address 对象。

private static IEnumerable<Address> Addresses(XContainer doc)
{
    XNamespace ns = "https://mws.amazonservices.com/Orders/2013-09-01";

    return from address in doc.Descendants(ns + "ShippingAddress")
           select new Address
           {
               Name = (string)address.Element(ns + "Name"),
               AddressLine1 = WebUtility.HtmlDecode((string)address.Element(ns + "AddressLine1")),
               AddressLine2 = (string)address.Element(ns + "AddressLine2"),
               City = (string)address.Element(ns + "City"),
               StateOrRegion = (string)address.Element(ns + "StateOrRegion"),
           };
}

请注意,您可以使用 WebUtility.HtmlDecode 来解码双重转义文本(例如,将 THE BOTIQUE &amp;amp; TAPES 解码为 THE BOTIQUE & TAPES)。这可能适用于所有行而不仅仅是 AddressLine1.

然后你可以用这样的签名实现你的 Excel 书写方法:

private static void WriteToExcel(IEnumerable<Address> addresses)

我将离开实施,因为不清楚你在 Excel_Create 中做什么 - 它似乎每次都重复覆盖 sheet 中的值的所有客户地址,所以我'我不确定目前的情况是否正确。

您的主要方法将减少为:

var path = Path.Combine(Directory.GetCurrentDirectory(), "Perls.xml");

var doc = XDocument.Load(path);

var addresses = Addresses(path);

WriteToExcel(addresses);

这里有一个将所有内容放在一起的工作演示:https://dotnetfiddle.net/k1AJ8H。这从 XML 字符串中读取并将地址写入控制台