2011-05-04 23 views
6

Tôi rất mới phân tích cú pháp XML và tôi bắt đầu tìm hiểu về LINQ mà tôi nghĩ có thể là giải pháp tốt nhất ở đây. Tôi chủ yếu quan tâm đến hiệu suất như các ứng dụng tôi đang tạo ra sẽ đọc giá chứng khoán, mà đôi khi có thể thay đổi rất nhanh chóng. tôi nhận được sau thông điệp từ máy chủ:Cách nhanh nhất/hiệu quả nhất để đọc XML này từ điển (LINQ hoặc cái gì khác?)

<?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> 

Mục đích của tôi là để phân tích các yếu tố mức giá

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

vào từ điển của cấu trúc sau:

Dictionary<double, PriceLevel> 

nơi giá phải là một double và PriceLevel là một lớp

class PriceLevel 
{ 
    int bid; 
    int offer; 

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


} 

Tùy thuộc vào yếu tố, trong đó mỗi điểm giá (hoặc giá thầu hoặc phiếu mua hàng) được chỉ định tương ứng, ví dụ: nếu giá giá tồn tại trong giá thầu, thì số lượng sẽ được chỉ định cho giá thầu và 0 để cung cấp. Ngược lại, nếu điểm giá tồn tại trong phiếu mua hàng, thì số lượng sẽ được chỉ định cho phiếu mua hàng và 0 để đặt giá thầu.

Tôi hy vọng lời giải thích của tôi là rõ ràng, tuy nhiên nếu bạn có bất kỳ vấn đề nào hiểu được, vui lòng không ngần ngại yêu cầu làm rõ trong nhận xét. Tôi sẽ đánh giá rất cao sự giúp đỡ trong việc giải quyết vấn đề này.

+++++++++++++++++++++++++++++++++++++++++ Cập nhật:

Tôi đã đi sâu hơn vào luồng mà tôi đang cố đọc, và nó sẽ không đơn giản như tôi mong đợi. Tôi phát hiện ra rằng luồng sẽ không luôn chứa toàn bộ tài liệu, do đó tôi sẽ phải đọc nó bằng cách sử dụng XmlReader để xử lý luồng liên tục. Trong trường hợp này, làm cách nào tôi có thể đọc giá thầu và phiếu mua hàng? Tôi có nội dung như sau:

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

nhưng tôi đang cố gắng liên kết tên phần tử với giá trị ... nghĩa là làm cách nào để biết giá giá thầu nào tôi hiện đang đọc và nếu điều này tồn tại trong giá thầu hoặc phiếu mua hàng? Cảm ơn bạn đã trợ giúp

+0

độ chính xác tối đa của điểm giá của bạn là bao nhiêu? bạn có tất cả chúng ở 1 chữ số thập phân, với 4 chữ số trước dp, trong ví dụ của bạn. Có phải đó là cách nó sẽ được cho tất cả các điểm giá của bạn? –

+0

Tốc độ nhanh nhất có thể là bao nhiêu? Giây, mili giây, micro giây? – Ishtar

+0

Tôi nghĩ rằng, độ chính xác tối đa 6 điểm thập phân là đủ. về tốc độ và hiệu suất, sẽ có rất nhiều thông báo tương tự mỗi giây vì vậy tôi đang nói miliseconds ít nhất;) – Macin

Trả lời

3

Khi đang sử dụng giao diện dựa trên sự kiện, tương tự như giao diện được trình bày trong bản cập nhật của bạn, bạn sẽ cần nhớ tên của sự kiện phần tử bắt đầu trước đó. Thường thì nó là giá trị trong khi giữ một ngăn xếp để theo dõi các sự kiện. Tôi có thể sẽ làm điều gì đó tương tự như sau:

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

Cảm ơn bạn Michael, đây là câu trả lời rất hữu ích! – Macin

0

Trước hết, tôi tin rằng phương pháp đưa vào từ điển của bạn sẽ dẫn đến lỗi. Nếu không sai, từ điển không thể có cùng khóa, vì vậy vì bạn đang sử dụng giá làm khóa, sẽ có rất nhiều cơ hội bạn gặp vấn đề này.

Tôi không thể nói về tốc độ, bạn phải kiểm tra. Nhưng cho đến nay XDocument chạy tốt cho tôi.
Sử dụng XDocument, tải các thông điệp toàn xml vào biến đó, ví dụ

XDocument doc = XDocument.Load(message); 

Với doc, bạn có thể sử dụng LINQ để nhóm chúng thành thầu và yêu cầu.

Khi bạn đạt được điều này, không nên có vấn đề trong việc trình bày dữ liệu của bạn khi bạn đã có giá và tách chúng thành giá mua và

+0

+1 cho va chạm chính, -1 cho đề xuất XDocument, mà không biết nếu nó là hiệu quả nhất. –

2

đầu tiên bạn cần để có được tất cả các cung cấp và tất cả chào giá

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

sau đó bạn chỉ cần lặp lại giá thầu và phiếu mua hàng và thêm chúng vào từ điển ... nhưng khi ai đó đang chờ trước ... bạn có thể gặp sự cố rằng giá tiền sẽ có cả giá thầu và phiếu mua hàng nếu chúng có cùng mức giá

để lặp lại throgugh the l IST bạn chỉ cần làm điều này

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

cùng bạn làm cho lời đề nghị ... nhưng một lần nữa .. .Bạn có thể phải kiểm tra xem phím này đã tồn tại ...

0

tôi quản lý để có được một cái gì đó như thế này :

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

Đây có phải là giải pháp thích hợp cho sự cố không? Tôi có một số nghi ngờ về đoạn mã này:

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

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

Tôi chỉ kích hoạt OnPricePointXảy ra sự kiện khi tôi đọc giá và số lượng. Tuy nhiên, có khả năng, rằng sẽ không có số lượng cho giá đã cho (hoặc không). Làm thế nào để thực hiện valiadation, để tránh lỗi dựa trên các thông điệp không đầy đủ?

Các vấn đề liên quan