2011-04-20 17 views
8

questo è un file OFX originale in quanto proviene da m banca (non preoccuparti, non c'è niente sensibile, ho tagliato la parte centrale con tutte le transazioni)Come analizzare questo file OFX?

Open Financial Exchange (OFX) è un data- formato di streaming per lo scambio di informazioni finanziarie evolute Connectivity (OFC) e Intuit's Open formati di file Exchange.

ora ho bisogno di analizzare questo. Ho già visto che question, ma questo non è un dup perché sono interessato a come farlo.

Sono sicuro che avrei potuto capire alcune regexps intelligenti che farebbero il lavoro, ma questo è brutto e vulnerabile agli errori (se il formato è cambiato, alcuni campi potrebbero mancare, la formattazione/gli spazi bianchi sono diversi ecc. Ecc. ..)

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> 

attualmente uso di questo codice che mi dà il risultato desiderato:

<? 

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

questo è veramente brutto e se questo era un file XML valido Io personalmente me ucciso per questo, ma come si fa meglio?

+3

Ragazzo, questo formato * fa schifo! * Sono sorpreso che non sia stato ancora pubblicato su thedailywtf. –

+0

Scommetto che hanno linee guida interne su microsoft per rendere orribile ai programmatori esterni un vantaggio commerciale: D –

+2

, inclusi i fogli di valutazione interni: quanti standard hai violato oggi? quanti formati esterni hai abusato? quanti software aperti hai rubato per vendere come il nostro? –

risposta

4

Il codice sembra buono, considerando che il file non è XML o SGML . L'unica cosa che potresti fare è provare a fare un parser più generico simile a SAX. Cioè, si passa semplicemente attraverso il flusso di input un blocco alla volta (in cui il blocco può essere qualsiasi cosa, ad esempio una riga o semplicemente una quantità di caratteri impostata). Quindi, chiamare una funzione di richiamata ogni volta che si incontra uno <ELEMENT>. Puoi anche essere fantasioso come costruire una classe di parser in cui puoi registrare le funzioni di callback che ascoltano elementi specifici.

Sarà più generico e meno "brutto" (per alcune definizioni di "brutto") ma sarà più codice da mantenere. Bello da fare e bello da avere se hai bisogno di analizzare questo formato di file molto (o in molte diverse varianti). Se il tuo codice pubblicato è l'unico posto in cui lo fai, allora solo KISS.

+0

sì, in realtà era la mia prima idea, scorrere le linee e spostare i puntatori interni secondo l'occorrenza del tag .. Scommetto che hanno linee guida interne per rendere difficile agli estranei un vantaggio commerciale: D –

+1

@Joe: in realtà, ho bisogno di correggermi. Secondo Wikipedia OFX è in effetti un SGML valido. Quindi, dovresti essere in grado di utilizzare qualsiasi parser SGML standard per analizzare questi file (probabilmente a condizione che tu abbia il 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);