2011-05-04 51 views
6

我是非常新的解析XML,我开始学习linq,我认为这可能是最好的解决方案。我最感兴趣的是性能,因为我创建的应用程序将读取股票交易所的价格,这些价格有时可能会非常迅速地变化。 我从服务器接收以下信息:什么是最快/最有效的方式来阅读这个XML字典(Linq或其他?)

<?xml version="1.0" encoding="utf-16"?> 
    <events> 
     <header> 
      <seq>0</seq> 
     </header> 
     <body> 
      <orderBookStatus> 
       <id>100093</id> 
       <status>Opened</status> 
      </orderBookStatus> 
      <orderBook> 
       <instrumentId>100093</instrumentId> 
       <bids> 
        <pricePoint> 
         <price>1357.1</price> 
         <quantity>20</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1357.0</price> 
         <quantity>20</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1356.9</price> 
         <quantity>71</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1356.8</price> 
         <quantity>20</quantity> 
        </pricePoint> 
       </bids> 
       <offers> 
        <pricePoint> 
         <price>1357.7</price> 
         <quantity>51</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1357.9</price> 
         <quantity>20</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1358.0</price> 
         <quantity>20</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1358.1</price> 
         <quantity>20</quantity> 
        </pricePoint> 
        <pricePoint> 
         <price>1358.2</price> 
         <quantity>20</quantity> 
        </pricePoint> 
       </offers> 
       <lastMarketClosePrice> 
        <price>1356.8</price> 
        <timestamp>2011-05-03T20:00:00</timestamp> 
       </lastMarketClosePrice> 
       <dailyHighestTradedPrice /> 
       <dailyLowestTradedPrice /> 
       <valuationBidPrice>1357.1</valuationBidPrice> 
       <valuationAskPrice>1357.7</valuationAskPrice> 
       <lastTradedPrice>1328.1</lastTradedPrice> 
       <exchangeTimestamp>1304501070802</exchangeTimestamp> 
      </orderBook> 
     </body> 
    </events> 

我的目标是解析的价格点元件

<pricePoint> 
     <price>1358.2</price> 
     <quantity>20</quantity> 
</pricePoint> 

成以下结构的词典:

Dictionary<double, PriceLevel> 

在价格应该是一个双和PriceLevel是一类

class PriceLevel 
{ 
    int bid; 
    int offer; 

    public PriceLevel(int b, int o) 
    { 
      bid = b; 
      offer = o; 
    } 


} 

根据元素的不同,每个价格点都存在(要么是出价或要约),因此应该相应地分配数量,即如果价格点存在于出价中,那么数量应该被分配给出价,并且0被提供。相反,如果报价中存在价格点,那么应该分配数量以提供报价,0报价。

我希望我的解释清楚,但是如果您在理解时有任何问题,请不要犹豫,在评论中要求澄清。 我非常感谢帮助解决这个问题。

+++++++++++++++++++++++++++++++++++++++++ 更新:

我已经深入到我正在尝试阅读的流中,而且它不会像我期望的那么简单。我发现,该流并不总是包含整个文档,因此我将不得不使用XmlReader读取它以持续处理流。在这种情况下,我如何阅读出价和优惠?我有这样的事情:

StreamReader sr = new StreamReader(“.. \ .. \ videos.xml”);

 XmlReader xmlReader = XmlReader.Create(sr); 
     while (xmlReader.Read()) 
     { 
      if (xmlReader.HasValue) 
      { 
       OnXmlValue(this, new MessageEventArgs(true, xmlReader.Value));//saxContentHandler.Content(xmlReader.Value); 
      } 
      else 
      { 
       if (xmlReader.IsEmptyElement) 
       { 
        OnStartElement(this, new MessageEventArgs(false, xmlReader.Name)); 
        OnEndElement(this, new MessageEventArgs(false, xmlReader.Name)); 
       } 
       else if (xmlReader.IsStartElement()) 
       { 
        OnStartElement(this, new MessageEventArgs(false, xmlReader.Name)); 
       } 
       else 
       { 
        OnEndElement(this, new MessageEventArgs(false, xmlReader.Name)); 
       } 
      } 
     } 

,但我很努力的元素名称链接到它的价值...即,我怎么能知道哪些标价点我目前正在读,如果存在的话在投标或报价? 谢谢你的帮助

+0

什么是您的价格点的最大准确性?你有他们所有的小数点后1位,在dp之前有4位数字,在你的例子中。这是如何为您的所有价格点? – 2011-05-04 10:09:30

+0

速度最快有多快?秒,毫秒,微秒? – Ishtar 2011-05-04 10:28:10

+0

我认为,6位小数的最大精度应该足够了。至于速度和性能,每秒钟会有很多类似的消息,所以我至少要说几毫秒;) – Macin 2011-05-04 11:24:21

回答

3

什么时候正在使用基于事件的界面,类似于更新中提供的界面,您将需要记住上一个开始元素事件的名称。通常,为了跟踪事件,持有堆栈是值得的。我可能会做类似于以下内容:

public class PriceLevel 
{ 
    private decimal? bid = null; 
    private decimal? offer = null; 

    public decimal? Bid { 
     get { return bid; } 
     set { bid = value; } 
    } 

    public decimal? Offer { 
     get { return offer; } 
     set { offer = value; } 
    } 
} 

public delegate void OnPriceChange(long instrumentId, Dictionary<decimal, PriceLevel> prices); 

public class MainClass 
{ 
    private Stack<String> xmlStack = new Stack<String>(); 
    private Dictionary<decimal, PriceLevel> prices = new Dictionary<decimal, PriceLevel>(); 
    private bool isBids = false; 
    private decimal? currentPrice = null; 
    private long instrumentId; 
    private OnPriceChange _priceChangeCallback; 

    public void MainClass(OnPriceChange priceChangeCallback) { 
     this._priceChangeCallback = priceChangeCallback; 
    } 

    public void XmlStart(object source, MessageEventArgs args) { 
     xmlStack.Push(args.Value); 

     if (!isBids && "bids" == args.Value) { 
      isBids = true; 
     } 
    } 

    public void XmlEnd(object source, MessageEventArgs args) { 
     xmlStack.Pop(); 

     if (isBids && "bids" == args.Value) { 
      isBids = false; 
     } 

     // Finished parsing the orderBookEvent 
     if ("orderBook" == args.Value) { 
      _priceChangeCallback(instrumentId, prices); 
     } 
    } 

    public void XmlContent(object source, MessageEventArgs args) { 

     switch (xmlStack.Peek()) { 
     case "instrumentId": 
      instrumentId = long.Parse(args.Value); 
      break; 

     case "price": 
      currentPrice = decimal.Parse(args.Value); 
      break; 

     case "quantity": 

      if (currentPrice != null) { 
       decimal quantity = decimal.Parse(args.Value); 

       if (prices.ContainsKey(currentPrice)) { 
        prices[currentPrice] = new PriceLevel(); 
       } 
       PriceLevel priceLevel = prices[currentPrice]; 

       if (isBids) { 
        priceLevel.Bid = quantity; 
       } else { 
        priceLevel.Offer = quantity; 
       } 
      } 
      break; 
     } 
    } 
} 
+0

谢谢迈克尔,这个非常有用的答案! – Macin 2011-05-11 20:22:47

0

首先,我相信你用字典的方法会导致错误。如果没有错,字典不能有相同的密钥,所以既然你使用价格作为关键,那么你很可能会遇到这个问题。

我不能说速度,你必须测试。但到目前为止,XDocument对我来说运行良好。
使用的XDocument,加载整个XML消息成变量,例如

XDocument doc = XDocument.Load(message); 

随着文档,你可以使用LINQ到它们分成买入价和卖出。

一旦你做到这一点,应出示您的数据,你已经得到了价格,并把他们分开成买入价和卖出

+0

+1关键冲突,-1表示XDocument,不知道它是否最有效。 – 2011-05-04 10:36:52

2

首先你需要获得所有优惠的所有投标没有问题,

XDocument xmlDoc = XDocument.Load("TestFile.xml"); 


var bids = (from b in xmlDoc.Descendants("bids") 
      select b).ToList(); 

var offers = (from o in xmlDoc.Descendants("offers") 
      select o).ToList(); 

那么你只是迭代throgh出价和优惠,并将它们添加到字典中......但是,因为有人在此之前出售过......你可能会遇到这样的问题:如果价格水平具有相同的价格,它将同时具有出价和出价设置

来迭代throgugh l IST你只是这样做

foreach (XElement e in bids) 
{ 
    price = e.Element("price").Value; 
    quantity = e.Element("quantity").Value; 
    dictionary.add(price, new PriceLevel(quantity,null); 
} 

您提供做...但再次...。你可能要检查,如果该键已经存在相同...

0

我设法得到这样的事情:

public void messageParser() 
    { 
     int i = 0; 
     bool readingBids = false; 
     bool readingOffers = false; 
     decimal price=0; 
     int qty = 0; 

     StreamReader sr = new StreamReader("..\\..\\sampleResponse.xml"); 

     XmlReader xmlReader = XmlReader.Create(sr); 
     DateTime startTime = DateTime.Now; 
     while (xmlReader.Read()) 
     { 
      #region reading bids 
      if (xmlReader.IsStartElement("bids")) 
      { 
       readingBids = true; 
       readingOffers = false; 
      } 

      if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "bids") 
      { 
       readingBids = false; 
       readingOffers = false; 
      } 

      if (readingBids == true) 
      { 
       if (xmlReader.IsStartElement("price")) 
        price = xmlReader.ReadElementContentAsDecimal(); 

       if (xmlReader.IsStartElement("quantity")) 
       { 
        qty = xmlReader.ReadElementContentAsInt(); 
        OnPricePointReceived(this, new MessageEventArgs(price, qty, "bid")); 
       } 
      } 
      #endregion 

      #region reading offers 
      if (xmlReader.IsStartElement("offers")) 
      { 
       readingBids = false; 
       readingOffers = true; 
      } 

      if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "offers") 
      { 
       readingBids = false; 
       readingOffers = false; 
      } 

      if (readingOffers == true) 
      { 
       if (xmlReader.IsStartElement("price")) 
        price = xmlReader.ReadElementContentAsDecimal(); 

       if (xmlReader.IsStartElement("quantity")) 
       { 
        qty = xmlReader.ReadElementContentAsInt(); 
        OnPricePointReceived(this, new MessageEventArgs(price, qty, "offer")); 
       } 
      } 
      #endregion 
     } 
     DateTime stopTime = DateTime.Now; 
     Console.WriteLine("time: {0}",stopTime - startTime); 
     Console.ReadKey(); 
    } 
} 

这是一个适当的解决方案的问题?我有一个关于这段代码有些疑惑:

if (readingBids == true) 
     { 
      if (xmlReader.IsStartElement("price")) 
       price = xmlReader.ReadElementContentAsDecimal(); 

      if (xmlReader.IsStartElement("quantity")) 
      { 
       qty = xmlReader.ReadElementContentAsInt(); 
       OnPricePointReceived(this, new MessageEventArgs(price, qty, "bid")); 
      } 
     } 

我只火OnPricePointReceived事件,当我设法阅读的价格和数量。但是,有可能,没有数量的给定价格(或不)。如何执行调用,以避免基于不完整消息的错误?

相关问题