1

我的目标

我需要根据 Placement_ID 和 Fill_ID 的组合创建一个在我的文档中出现动态次数的 XElement。如果我的对象列表中的记录与另一条记录具有相同的 Placement_ID,我想在前一个下方附加另一个具有不同 Fll_ID 的填充 XElement。下面的例子:

<envelope ack="entity" transaction="multi">
  <auth>
        <user>TM_DEV</user>
        <session>session1</session>
  </auth>
  <Trading op="createOrder, pretradeCpl, sendToTrading,createPlacement, createFill" id="os1">
        <order op="create" id="test1234">
              <scenario id="sample" />
              <execBroker>BEAR</execBroker>
              <ticker>MSFT</ticker>
              <trader>TM_DEV</trader>
              <instruction>LIM</instruction>
              <limitPrice>85</limitPrice>
              <transType>BUYL</transType>
              <orderDuration>GTC</orderDuration>
              <tradeDate>
              </tradeDate>
              <settleDate>
              </settleDate>
              <allocation id="" op="create">
                    <acctCd>tstacc00006</acctCd>
                    <targetQty>300</targetQty>
                    <specialInst />
              </allocation>
              <placement id="Place1" op="create">
                    <execBroker>BEAR</execBroker>
                    <placeQty>300</placeQty>
                    <fill id="fill1" op="create">
                          <fillQty>150</fillQty>
                          <fillPrice>43</fillPrice>
                    </fill>
                    <fill id="fill2" op="create">
                          <fillQty>150</fillQty>
                          <fillPrice>44</fillPrice>
                    </fill>
              </placement>
        </order>
  </Trading>

我的进步

到目前为止,我编写的下面的代码查询一个列表对象并为每一行生成一个新顺序。我需要能够按 Placement_ID 对我的列表进行分组,如果它们是具有相同 Placement_ID 的两行,那么我希望它编写多个 Fill 元素。否则,如果没有重复的 Placement_ID,则列表中的每一行数据将有 1 个订单、1 个放置和 1 个填充。

XDocument doc = new XDocument(
           new XDeclaration("1.0", "UTF-8", "yes"),
          new XElement("envelope",
          new XAttribute("ack", "entity"),
          new XAttribute("transaction", "multi"),
           new XElement("auth",
           new XElement("user", "TM_DEV"),
           new XElement("session", "session1")),
           new XElement("trading",
               new XAttribute("op", "createOrder, pretradeCpl, sendToTrading, createPlacement, createFill"),
               new XAttribute("id", "os1"),
           from t in trades.ToList()
           select new XElement("order",
                   new XAttribute("op", "create"),
                   new XAttribute("id", DateTime.Now.ToString("yyMMddHHmmssfff") + t.OrderId),
                   new XElement("Scenario",
                       new XAttribute("id", "sample")),
                   new XElement("execBroker", t.ExecBrkID),
                   new XElement("ticker", t.Ticker),
                   new XElement("sedol", t.Sedol),
                   new XElement("Trader", "TM_DEV"),
                   new XElement("transType", t.TransType),
                   new XElement("orderDuration", "GTC"),
                   new XElement("tradeDate", ""),
                   new XElement("settleDate", ""),
                   new XElement("allocation",
                       new XAttribute("id", ""),
                       new XAttribute("op", "create"),
                       new XElement("acctCd", t.Account),
                       new XElement("targetQty", t.TargetQty),
                       new XElement("specialInst", "who to settle with")),
                   new XElement("placement",
                       new XAttribute("op", "create"),
                       new XAttribute("id", t.PlacementId),
                       new XElement("execBroker", t.ExecBrkID),
                       new XElement("placeQty", t.ExecQty),
                       new XElement("fill",
                           new XAttribute("id", t.FillId),
                           new XAttribute("op", "create"),
                       new XElement("fillQty", t.ExecQty),
                       new XElement("fillPrice", t.ExecPrice)))))));

更新

我已经使用您的建议分解了更新中的示例。现在我收到“文档格式不正确”的错误。

using (XmlWriter xw = XmlWriter.Create(s, xws)){


XElement order = new XElement("order");
var groupedOrders = trades.GroupBy(o => o.OrderId);

foreach (var groupie in groupedOrders)
{
    int n = 1;
    XElement root = new XElement("placement",
                    from g in groupie
                       select new XElement("t",
                                new XAttribute("op", "create"),
                              new XAttribute("id", g.Ticker)));                    
    foreach (var fill in groupie)
    {
        XElement newFillElement = new XElement("fill" + n,
                                    new XAttribute("id", fill.PlacementId),
                                   new XAttribute("op", "create"),
                                    new XElement("fillQty", fill.ExecQty),
                                    new XElement("fillPrice", fill.ExecPrice));
        root.Add(newFillElement);
        n++;   
    }

    order.Add(root);
}

XDocument doc = new XDocument(
                    new XDeclaration("1.0", "UTF-8", "yes"), order);
doc.Save(xw);

}

4

2 回答 2

1

乍一看,您似乎一次次尝试做太多事情。我认为创建基础文档很好,但如果您需要有条件地添加填充,那么您需要不同的策略。

我建议您在循环之前使用 LINQ 按 Placement_ID 对订单进行分组。这将确保组元素具有相同的 Placement_ID - 并允许您添加适当数量的fills.

一些伪代码:

var groupedOrders = listOfOrders.GroupBy(o => o.Placement_ID);
foreach (var group in groupedOrders)
{
    //Create document, but don't add any fills
    XDocument doc = new XDocument(...)

    int n = 1;
    foreach (var fill in group)
    {
        //Same structure as before, just a separate element
        XElement newFillElement = new XElement("fill" + n, ...);

        //Add as last element to existing doc
        doc.Add(newFillElement);

        n++
    }
}

参考:
101 个 LINQ 示例,LINQ -
在 XML 中添加、更新和删除数据的分组运算符

于 2012-12-27T21:02:27.763 回答
0

您能否在 xml 构建之外创建关系,然后从中重建 xml?从你看来,这可能更容易。您可能会创建一个通用列表,其中包含您想要的元素和属性 xml 中的所有数据。将xml转储到其中,然后将其导出。添加将是一组规则的动态扩展事物。使用 Linq to XML 将 xml 查询到通用列表中。

我不会做像你的例子那样激烈的事情,因为你只需要理解一个概念。您也可以直接在“后代”方法中进行计数和其他操作,但我通常更喜欢先将内容列在列表中,然后我知道我有什么

以 XML 为例:

<Orders>
  <Person Name="Brett">
    <Order Name="thing"/>
  </Person>
  <Person Name="Joe">
   <Order Name="thing"/>
   <Order Name="thing2" />
  </Person>
</Orders>

C# 示例:

using System;
using System.Linq;
using System.Xml.Linq;

namespace TestLinqXml
{
    public class Program
    {
        private static void Main(string[] args)
        {
            // load original doc
            var doc = XDocument.Load(@"C:\TestCode\TestLinqXml\TestLinqXml\XML\Orders.xml");

            // query it with Linq using lambda patterns.
            var list = doc.Descendants("Person")
                          .Select(x => new 
                                  // expand descendents out into a class I make up below by declarining new and defining object
                                  {
                                      Name = x.Attribute("Name").Value,
                                      OrderCount = x.Descendants("Order").Count()
                                  }
                );

            // recreate the new doc
            XDocument newdoc = new XDocument(
                new XDeclaration("1.0", "UTF-8", "yes"),
                new XElement("person",
                             list.Select(n =>
                                         new XElement(n.Name,
                                                      new XAttribute("OrderCount", n.OrderCount)
                                             ))
                    )
                );

            // save it
            newdoc.Save(@"C:\TestCode\TestLinqXml\TestLinqXml\XML\output.xml");
        }
    }
}
于 2012-12-27T22:02:01.463 回答