2011-04-20 31 views
8

đây là một file OFX gốc vì nó xuất phát từ m ngân hàng (không phải lo lắng, theres không có gì nhạy cảm, tôi cắt bỏ phần giữa với tất cả các giao dịch)Cách phân tích cú pháp tệp OFX này?

mở Financial Exchange (OFX) là một đĩa dữ liệu định dạng luồng để trao đổi thông tin tài chính phát triển từ Tài chính mở của Microsoft Khả năng kết nối (OFC) và Định dạng tệp trao đổi mở của Intuit .

bây giờ tôi cần phải phân tích cú pháp này. tôi đã thấy rằng question, nhưng đây không phải là một dup vì tôi quan tâm đến cách làm điều này.

Tôi chắc chắn tôi có thể tìm ra một số quy tắc thông minh có thể thực hiện công việc, nhưng điều đó là xấu và dễ bị lỗi (nếu định dạng bị thay đổi, một số trường có thể bị thiếu, định dạng/khoảng trắng khác nhau, v.v. ..)

OFXHEADER:100 
DATA:OFXSGML 
VERSION:102 
SECURITY:NONE 
ENCODING:USASCII 
CHARSET:1252 
COMPRESSION:NONE 
OLDFILEUID:NONE 
NEWFILEUID:NONE 
<OFX> 
    <SIGNONMSGSRSV1> 
     <SONRS> 
      <STATUS> 
       <CODE>0 
       <SEVERITY>INFO 
      </STATUS> 
      <DTSERVER>20110420000000[+1:CET] 
      <LANGUAGE>ENG 
     </SONRS> 
    </SIGNONMSGSRSV1> 
    <BANKMSGSRSV1> 
     <STMTTRNRS> 
      <TRNUID>1 
      <STATUS> 
       <CODE>0 
       <SEVERITY>INFO 
      </STATUS> 
      <STMTRS> 
       <CURDEF>EUR 
       <BANKACCTFROM> 
        <BANKID>20404 
        <ACCTID>02608983629 
        <ACCTTYPE>CHECKING 
       </BANKACCTFROM> 
        <BANKTRANLIST> 
        <DTSTART>20110207 
        <DTEND>20110419 
        <STMTTRN> 
         <TRNTYPE>XFER 
         <DTPOSTED>20110205000000[+1:CET] 
         <TRNAMT>-6.12 
         <FITID>C74BD430D5FF2521 
         <NAME>unbekannt 
         <MEMO>BILLA DANKT 1265P K2 05.02.UM 17.49 
        </STMTTRN> 
        <STMTTRN> 
         <TRNTYPE>XFER 
         <DTPOSTED>20110207000000[+1:CET] 
         <TRNAMT>-10.00 
         <FITID>C74BE0F90A657901 
         <NAME>unbekannt 
         <MEMO>AUTOMAT 13177 KARTE2 07.02.UM 10:22 
        </STMTTRN> 
............................. goes on like this ........................ 
        <STMTTRN> 
         <TRNTYPE>XFER 
         <DTPOSTED>20110418000000[+1:CET] 
         <TRNAMT>-9.45 
         <FITID>C7A5071492D14D29 
         <NAME>unbekannt 
         <MEMO>HOFER DANKT 0408P K2 18.04.UM 18.47 
        </STMTTRN> 
       </BANKTRANLIST> 
       <LEDGERBAL> 
        <BALAMT>1992.29 
        <DTASOF>20110420000000[+1:CET] 
       </LEDGERBAL> 
      </STMTRS> 
     </STMTTRNRS> 
    </BANKMSGSRSV1> 
</OFX> 

tôi hiện đang sử dụng mã này mang đến cho tôi những kết quả mong muốn:

<? 

$files = array(); 
$files[] = '***_2011001.ofx'; 
$files[] = '***_2011002.ofx'; 
$files[] = '***_2011003.ofx'; 

system('touch file.csv && chmod 777 file.csv'); 
$fp = fopen('file.csv', 'w'); 

foreach($files as $file) { 
    echo $file."...\n"; 
    $content = file_get_contents($file); 

    $content = str_replace("\n","",$content); 
    $content = str_replace(" ","",$content); 

    $regex = '|<STMTTRN><TRNTYPE>(.+?)<DTPOSTED>(.+?)<TRNAMT>(.+?)<FITID>(.+?)<NAME>(.+?)<MEMO>(.+?)</STMTTRN>|'; 


    echo preg_match_all($regex,$content,$matches,PREG_SET_ORDER)." matches... \n"; 


    foreach($matches as $match) { 
     echo "."; 
     array_shift($match); 
     fputcsv($fp, $match); 
    } 
    echo "\n"; 
} 
echo "done.\n"; 
fclose($fp); 

này là thực sự xấu xí và nếu điều này là một tập tin xml hợp lệ cá nhân tôi sẽ giết bản thân mình vì điều đó, nhưng làm thế nào để làm điều đó tốt hơn?

+3

Boy, định dạng này * stinks! * Tôi rất ngạc nhiên vì nó chưa được xuất hiện trên thedailywtf. –

+0

tôi đặt cược họ có hướng dẫn nội bộ tại microsoft để làm cho nó kinh khủng cho các lập trình viên bên ngoài để đạt được lợi thế kinh doanh: D –

+2

bao gồm cả bảng đánh giá nội bộ: bạn đã vi phạm tiêu chuẩn bao nhiêu ngày hôm nay? bạn đã lạm dụng bao nhiêu định dạng bên ngoài? bạn đã ăn cắp bao nhiêu phần mềm mở như của riêng mình? –

Trả lời

4

Mã của bạn có vẻ tốt, cho rằng tệp không phải là XML hoặc thậm chí SGML . Điều duy nhất bạn có thể làm là cố gắng tạo một trình phân tích cú pháp giống như SAX chung hơn. Tức là, bạn chỉ cần đi qua luồng đầu vào một khối tại một thời điểm (nơi khối có thể là bất kỳ thứ gì, ví dụ: một dòng hoặc đơn giản là một số lượng ký tự được đặt). Sau đó, gọi một hàm gọi lại mỗi khi bạn gặp một số <ELEMENT>. Bạn thậm chí có thể đi như huyền ảo như xây dựng một lớp phân tích cú pháp, nơi bạn có thể đăng ký chức năng gọi lại mà lắng nghe các yếu tố cụ thể.

Nó sẽ chung chung hơn và ít "xấu xí" (đối với một số định nghĩa "xấu xí") nhưng sẽ có nhiều mã hơn để duy trì. Rất vui được làm và rất hay nếu bạn cần phân tích định dạng tệp này rất nhiều (hoặc trong nhiều biến thể khác nhau). Nếu mã được đăng của bạn là nơi duy nhất bạn làm điều này thì chỉ cần KISS.

+0

yeah đó thực sự là ý tưởng đầu tiên của tôi, lặp qua các dòng và thay đổi con trỏ nội bộ theo sự xuất hiện của thẻ .. Tôi đặt cược rằng họ có hướng dẫn nội bộ để làm cho nó khó khăn cho người ngoài để đạt được một lợi thế kinh doanh: D –

+1

@ Joe: thực sự, tôi cần phải sửa bản thân mình. Theo Wikipedia OFX thực ra là SGML hợp lệ. Vì vậy, bạn sẽ có thể sử dụng bất kỳ trình phân tích cú pháp SGML chuẩn nào để phân tích các tệp này (có thể được cung cấp rằng bạn có DTD). –

0
// Load Data String  
    $str = file_get_contents($fLoc); 
    $MArr = array(); // Final assembled master array 
// Fetch all transactions 
    preg_match_all("/<STMTTRN>(.*)<\/STMTTRN>/msU",$str,$m); 
    if (!empty($m[1])) { 
     $recArr = $m[1]; unset($str,$m); 
     // Parse each transaction record 
     foreach ($recArr as $i => $str) { 
      $_arr = array(); 
      preg_match_all("/(^\s*<(?'key'.*)>(?'val'.*)\s*$)/m",$str,$m); 
      foreach ($m["key"] as $i => $key) { 
       $_arr[$key] = trim($m["val"][$i]); // Reassemble array key => val 
      } 
      array_push($MArr,$_arr); 
     } 
    } 
    print_r($MArr); 
Các vấn đề liên quan