如何解析这个OFX文件?

The*_*can 9 php regex xml parsing ofx

这是一个原始的ofx文件,因为它来自m银行(不用担心,没有什么敏感,我切断了所有交易的中间部分)

Open Financial Exchange(OFX)是一种数据流格式,用于交换从Microsoft的开放式金融连接(OFC)和Intuit的Open Exchange文件格式演变而来的财务信息.

现在我需要解析这个.我已经看到了这个问题,但这不是重复,因为我对如何做到这一点很感兴趣.

我相信我可以找到一些聪明的正则表达式来完成这项工作,但这很难看并且容易出错(如果格式发生变化,某些字段可能会丢失,格式化/空格不同等等......)

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>
Run Code Online (Sandbox Code Playgroud)

我目前使用此代码,它给了我想要的结果:

<?

$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);
Run Code Online (Sandbox Code Playgroud)

这真是太丑了,如果这是一个有效的xml文件,我个人会为此自杀,但如何做得更好?

San*_*hal 5

考虑到该文件不是XML 甚至SGML,您的代码似乎很好.你唯一能做的就是尝试制作一个更通用的SAX解析器.也就是说,您只需一次一个块地输入输入流(其中块可以是任何内容,例如一行或只是一定数量的字符).然后,每次遇到时都调用回调函数<ELEMENT>.您甚至可以像构建解析器类一样幻想,您可以在其中注册侦听特定元素的回调函数.

它将更通用,更少"丑陋"(对于某些"丑陋"的定义),但它将维护更多的代码.如果你需要解析这个文件格式(或者在很多不同的版本中),那么很高兴并且很高兴.如果您发布的代码是您执行此操作的唯一位置,那么只需KISS.

  • @Joe:实际上,我需要纠正自己。根据维基百科 OFX 实际上是有效的 SGML。因此,您应该能够使用任何标准的 SGML 解析器来解析这些文件(可能前提是您拥有 DTD)。 (2认同)