挑战重组XML

时间:2017-11-02 19:53:59

标签: c# xml linq

我有一个如下所示的XML文件:

<SalesOrders>
    <Header>
        <CustomerID>456554</CustomerID>
        <BuyerID>312</BuyerID>
        <OrderNbr>S392392</OrderNbr>
    </Header>
    <Item>
        <Item>E565-14</Item>
        <Quantity>65</Quantity>
        <Price>33.45</Price>
    </Item>
    <Item>
        <Item>G916-22</Item>
        <Quantity>654</Quantity>
        <Price>655.22</Price>
    </Item>
    <Header>
        <CustomerID>156557</CustomerID>
        <BuyerID>35</BuyerID>
        <OrderNbr>S394545</OrderNbr>
    </Header>
    <Item>
        <Item>GS654-88</Item>
        <Quantity>78</Quantity>
        <Price>2.11</Price>
    </Item>
</SalesOrders>

我想重构我的XML,以便我有Header&amp;项目内 订购这样的节点:

<SalesOrders>
    <Order>
        <Header>
            <CustomerID>456554</CustomerID>
            <BuyerID>312</BuyerID>
            <OrderNbr>S392392</OrderNbr>
        </Header>
        <Item>
            <Item>E565-14</Item>
            <Quantity>65</Quantity>
            <Price>33.45</Price>
        </Item>
        <Item>
            <Item>G916-22</Item>
            <Quantity>654</Quantity>
            <Price>655.22</Price>
        </Item>
    </Order>
    <Order>
        <Header>
            <CustomerID>156557</CustomerID>
            <BuyerID>35</BuyerID>
            <OrderNbr>S394545</OrderNbr>
        </Header>
        <Item>
            <Item>GS654-88</Item>
            <Quantity>78</Quantity>
            <Price>2.11</Price>
        </Item>
    </Order>
</SalesOrders>

我熟悉C#,也知道一些LINQ。我似乎无法从我所寻找的在线示例中找到如何做到这一点的正确示例 是否有人可以发布如何实现这一目标的例子?

谢谢

我为不包含代码而道歉。此代码实际上将许多单独的XML文件合并为一个XML文件。我最初的计划是在创建最终输出XML文件后将Order节点添加到XML中。也许这不是最好的方法吗?我对所有建议持开放态度。这是代码:

public void CombineXMLFiles()
{
    string[] XMLFiles = null;
    XmlDocument CombineXMLDoc = new XmlDocument();
    CombineXMLDoc.LoadXml("<SalesOrders></SalesOrders>");
    XMLFiles = Directory.GetFiles("e:\\data\\xml\\", "529485*.xml");
    foreach (void FileName_loopVariable in XMLFiles) {
        FileName = FileName_loopVariable;
        FileInfo FileInfo = new FileInfo(FileName);
        if (FileInfo.Length <= 0) {
            File.Delete(FileName);
            continue;
        }
        XmlDocument OrderXMLDoc = new XmlDocument();
        OrderXMLDoc.Load(FileName);
        foreach (XmlNode Node in OrderXMLDoc.DocumentElement.ChildNodes) {
            switch (Node.Name.ToUpper) {
                case "HEADER":
                    XmlNode OrderNode = CombineXMLDoc.ImportNode(Node, true);
                    CombineXMLDoc.DocumentElement.AppendChild(OrderNode);
                    break;
                case "ITEM":
                    XmlNode OrderNode = CombineXMLDoc.ImportNode(Node, true);
                    CombineXMLDoc.DocumentElement.AppendChild(OrderNode);
                    break;
                default:
                    continue;
            }
        }
    }
    string dtStamp = DateTime.Now.ToString("yyyyMMddHHmmss");
    CombineXMLFileName = "e:\\data\\xml\\output\\" + "STC_" + dtStamp + ".XML";
    CombineXMLDoc.Save(CombineXMLFileName);
}

2 个答案:

答案 0 :(得分:0)

此Linq to XML代码将您的第一个XML样本置换为第二个。如果您需要将多个文件中的第一个XML拼凑在一起,那么将xdoc放在一起可能会比这更复杂。

您可以将此逻辑简单地转换为foreach循环。关于你正在尝试做什么,一点也不困难。

var xdoc = XDocument.Parse(xml);

var headersWithItems = 
    xdoc.Descendants("Header")
    .Select(h => new {
        Header = h,
        Items = h.ElementsAfterSelf().TakeWhile(e => e.Name == "Item") })
    ;

var salesOrders =
    new XElement("SalesOrders",
        headersWithItems.Select(
                hwi =>
                {
                    var e = new XElement("Order", hwi.Header);
                    e.Add(hwi.Items.ToArray());
                    return e;
                }
            ).ToArray()
        );

答案 1 :(得分:0)

我会使用xml linq做一些不同的事情。只是风格差异

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 salesOrder = doc.Descendants("SalesOrders").FirstOrDefault();
            List<XElement> children = salesOrder.Elements().ToList();

            XElement order = null;
            foreach (XElement child in children)
            {
                if (child.Name.LocalName == "Header")
                {
                    order = new XElement("Order");
                    salesOrder.Add(order);

                }
                order.Add(child);
                child.Remove();
            }
        }
    }
}