2013-03-31 6 views
6

CitibankからOFXファイルをダウンロードしました。このファイルのDTDはhttp://www.ofx.net/DownloadPage/Files/ofx102spec.zip(OFXBANK.DTDファイル)と定義されています.OFXファイルはSGMLと表示されます。 PHP 5.4.13のDomDocumentで試していますが、いくつかの警告が表示され、ファイルは解析されません。私のコードは次のとおりです。PHPでOFX(バージョン1.0.2)ファイルを解析するには?

$file = "source/ACCT_013.OFX"; 
$dtd = "source/ofx102spec/OFXBANK.DTD"; 
$doc = new DomDocument(); 
$doc->loadHTMLFile($file); 
$doc->schemaValidate($dtd); 
$dom->validateOnParse = true; 

OFXファイルの先頭として:

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>20130331073401 
<LANGUAGE>SPA 
</SONRS> 
</SIGNONMSGSRSV1> 
<BANKMSGSRSV1> 
<STMTTRNRS> 
<TRNUID>0 
<STATUS> 
<CODE>0 
<SEVERITY>INFO 
</STATUS> 
<STMTRS> 
<CURDEF>COP 
<BANKACCTFROM> ... 

私はPHPからの呼び出しをサーバ(CentOSに)で任意のプログラムをインストールして使用して開いています。

PD:このクラスhttp://www.phpclasses.org/package/5778-PHP-Parse-and-extract-financial-records-from-OFX-files.htmlは私にとっては機能しません。

答えて

3

まず最初に、XMLはSGMLのサブセットです。有効なSGMLファイルは整形式のXMLファイルであってはいけません。 XMLはより厳密であり、SGMLが提供するすべての機能を使用しません。

DOMDocumentはXMLベースであり、SGMLベースではありませんが、これは実際には互換性がありません。その問題へ次

、オープン金融取引所のファイルの

内容が内容に続いて、ヘッダーの簡単なセットで構成されていること、それはあなたを説明しOfexfin1.docに2.2オープン金融取引所ヘッダを参照してください。そのヘッダに

さらにによって定義される:

ブランク行が最後に従いますヘッダ。次に(OFXSGMLタイプの場合)、SGML読み取り可能データは< OFX>タグで始まります。

したがって、最初の空白行を見つけてそこまで縞模様にします。最初XMLにSGMLを変換することによってのDOMDocumentにSGMLの一部をロード:

<?xml version="1.0"?> 
<OFX> 
    <SIGNONMSGSRSV1> 
    <SONRS> 
     <STATUS> 
     <CODE>0</CODE> 
     <SEVERITY>INFO</SEVERITY> 
     </STATUS> 
     <DTSERVER>20130331073401</DTSERVER> 
     <LANGUAGE>SPA</LANGUAGE> 
    </SONRS> 
    </SIGNONMSGSRSV1> 
    <BANKMSGSRSV1> 
    <STMTTRNRS> 
     <TRNUID>0</TRNUID> 
     <STATUS> 
     <CODE>0</CODE> 
     <SEVERITY>INFO</SEVERITY> 
     </STATUS> 
     <STMTRS><CURDEF>COP</CURDEF><BANKACCTFROM> ...</BANKACCTFROM> 
</STMTRS> 
    </STMTTRNRS> 
    </BANKMSGSRSV1> 
</OFX> 
を:

$source = fopen('file.ofx', 'r'); 
if (!$source) { 
    throw new Exception('Unable to open OFX file.'); 
} 

// skip headers of OFX file 
$headers = array(); 
$charsets = array(
    1252 => 'WINDOWS-1251', 
); 
while(!feof($source)) { 
    $line = trim(fgets($source)); 
    if ($line === '') { 
     break; 
    } 
    list($header, $value) = explode(':', $line, 2); 
    $headers[$header] = $value; 
} 

$buffer = ''; 

// dead-cheap SGML to XML conversion 
// see as well http://www.hanselman.com/blog/PostprocessingAutoClosedSGMLTagsWithTheSGMLReader.aspx 
while(!feof($source)) { 

    $line = trim(fgets($source)); 
    if ($line === '') continue; 

    $line = iconv($charsets[$headers['CHARSET']], 'UTF-8', $line); 
    if (substr($line, -1, 1) !== '>') { 
     list($tag) = explode('>', $line, 2); 
     $line .= '</' . substr($tag, 1) . '>'; 
    } 
    $buffer .= $line ."\n"; 
} 

// use DOMDocument with non-standard recover mode 
$doc = new DOMDocument(); 
$doc->recover = true; 
$doc->preserveWhiteSpace = false; 
$doc->formatOutput = true; 
$save = libxml_use_internal_errors(true); 
$doc->loadXML($buffer); 
libxml_use_internal_errors($save); 

echo $doc->saveXML(); 

このコード例は、その後ものDOMDocumentが適切にデータをロードすることを示す(再フォーマットされた)次のXMLを出力します

DTDに対してこれを検証できるかどうかわかりません。たぶんこれはうまくいくでしょう。さらに、SGMLに同じ行のタグである値が書き込まれていない場合(そして各行の要素が1つだけ必要な場合)、この壊れやすい変換は中断されます。

+0

ありがとうございます。それはhttp://www.bin-co.com/php/scripts/xml2array/ –

+0

でPHP配列に変換されましたが、フォーマットはやや平らになっています。この変種を使用したいと思うかもしれません:http://stackoverflow.com/a/15729905/367456 - これは1行のコードです。 – hakre

1

最も単純なOFXは、すべての値とトランザクションに簡単にアクセスできる配列を解析します。

function parseOFX($ofx) { 
    $OFXArray=explode("<",$ofx); 
    $a=array(); 
    foreach ($OFXArray as $v) { 
     $pair=explode(">",$v); 
     if (isset($pair[1])) { 
      if ($pair[1]!=NULL) { 
       if (isset($a[$pair[0]])) { 
        if (is_array($a[$pair[0]])) { 
         $a[$pair[0]][]=$pair[1]; 
        } else { 
         $temp=$a[$pair[0]]; 
         $a[$pair[0]]=array(); 
         $a[$pair[0]][]=$temp; 
         $a[$pair[0]][]=$pair[1]; 
        } 
       } else { 
        $a[$pair[0]]=$pair[1]; 
       } 
      } 
     } 
    } 
    return $a; 
}