2011-04-20 19 views
8

इस एक मूल OFX फाइल के रूप में मीटर बैंक से आता हैइस OFX फ़ाइल को कैसे पार्स करें?

ओपन वित्तीय एक्सचेंज (OFX) एक डेटा- है (कोई चिंता नहीं, संवेदनशील कुछ भी नहीं theres, मैं सभी लेनदेन के साथ मध्य भाग को काट) वित्तीय जानकारी है कि माइक्रोसॉफ्ट के ओपन वित्तीय कनेक्टिविटी (ओएफसी) और Intuit ओपन एक्सचेंज फ़ाइल स्वरूपों से विकसित का आदान प्रदान के लिए स्ट्रीम प्रारूप।

अब मैं इस पार्स करने के लिए की जरूरत है। मैंने पहले ही question देखा है, लेकिन यह एक डुप्लिकेट नहीं है क्योंकि मुझे यह करने में दिलचस्पी है।

मुझे यकीन है कि मैं कुछ चालाक regexps पता लगा सकता है जो नौकरी करेगा, लेकिन यह बदसूरत और त्रुटि कमजोर है (अगर प्रारूप बदल गया है, तो कुछ फ़ील्ड गायब हो सकते हैं, स्वरूपण/सफेद रिक्त स्थान इत्यादि आदि हैं। ..)

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> 

मैं वर्तमान में उपयोग के लिए इस कोड जो मुझे वांछित परिणाम देता है:

<? 

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

यह वास्तव में बदसूरत है और अगर यह एक वैध xml फ़ाइल था मैं व्यक्तिगत रूप से उस के लिए अपने आप को मार डालेंगे, लेकिन इसे बेहतर कैसे करें?

+3

लड़का, यह प्रारूप * बदबू आ रही है! * मुझे आश्चर्य है कि यह अभी तक thedailywtf पर प्रदर्शित नहीं किया गया है। –

+0

मैं शर्त लगाता हूं कि माइक्रोसॉफ्ट में आंतरिक प्रोग्रामर को व्यावसायिक लाभ प्राप्त करने के लिए यह भयानक बनाने के लिए आंतरिक मार्गदर्शिकाएं हैं: डी –

+2

आंतरिक मूल्यांकन पत्रक सहित: आज आपने कितने मानक का उल्लंघन किया? आपने कितने बाहरी प्रारूपों का दुरुपयोग किया? आपने खुद को बेचने के लिए कितने खुले सॉफ्टवेयर चुराए? –

उत्तर

4

आपका कोड ठीक लग रहा है, यह देखते हुए कि फ़ाइल XML या यहाँ तक कि SGML नहीं है। एकमात्र चीज जो आप कर सकते हैं वह एक अधिक सामान्य सैक्स-जैसे पार्सर बनाने का प्रयास करें। यही है, आप बस एक समय में इनपुट स्ट्रीम एक ब्लॉक से गुज़रते हैं (जहां ब्लॉक कुछ भी हो सकता है, उदाहरण के लिए एक रेखा या बस वर्णों की एक निश्चित मात्रा)। फिर, हर बार जब आप <ELEMENT> सामना करते हैं तो कॉलबैक फ़ंक्शन को कॉल करें। आप एक पार्सर क्लास के निर्माण के रूप में भी प्रशंसनीय हो सकते हैं जहां आप कॉलबैक फ़ंक्शन पंजीकृत कर सकते हैं जो विशिष्ट तत्वों को सुनते हैं।

यह ("बदसूरत" के कुछ परिभाषा के लिए) अधिक सामान्य और कम "बदसूरत" हो जाएगा, लेकिन यह बनाए रखने के लिए अधिक कोड होगा। अच्छा करने के लिए अच्छा है और अगर आपको इस फ़ाइल को बहुत अधिक प्रारूपित करने की आवश्यकता है (या कई अलग-अलग बदलावों में)। यदि आपका पोस्ट कोड एकमात्र ऐसा स्थान है जहां आप ऐसा करते हैं तो बस KISS

+0

हाँ कि वास्तव में मेरी पहली विचार था, लाइनों के माध्यम से पाशन और टैग occourence के अनुसार आंतरिक संकेत दिए गए बदलाव .. मैं शर्त लगाता हूं कि बाहरी लोगों के लिए व्यावसायिक लाभ हासिल करना मुश्किल हो गया है: डी –

+1

@ जो: वास्तव में, मुझे खुद को सही करने की आवश्यकता है। विकिपीडिया ऑफएक्स के अनुसार वास्तव में वैध एसजीएमएल है। इसलिए, आप इन फ़ाइलों को पार्स करने के लिए किसी भी मानक एसजीएमएल पार्सर का उपयोग करने में सक्षम होना चाहिए (शायद यह उपलब्ध कराया गया है कि आपके पास डीटीडी है)। –

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); 
संबंधित मुद्दे