2013-03-31 36 views
6

Tôi có tệp OFX được tải xuống từ Citibank, tệp này có DTD được xác định tại http://www.ofx.net/DownloadPage/Files/ofx102spec.zip (tệp OFXBANK.DTD), tệp OFX có vẻ là SGML hợp lệ. Tôi đang thử với DomDocument của PHP 5.4.13, nhưng tôi nhận được một số cảnh báo và tệp không được phân tích cú pháp. Mã của tôi là:Làm thế nào để phân tích cú pháp tệp OFX (Phiên bản 1.0.2) bằng PHP?

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

File OFX bắt đầu như:

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> ... 

Tôi mở để cài đặt và sử dụng bất kỳ chương trình trong Server (Centos) cho cuộc gọi từ PHP.

PD: Lớp học này http://www.phpclasses.org/package/5778-PHP-Parse-and-extract-financial-records-from-OFX-files.html không hoạt động đối với tôi.

Trả lời

3

Trước tiên, ngay cả XML là một tập con của SGML một tệp SGML hợp lệ không được là một tệp XML được định dạng tốt. XML nghiêm ngặt hơn và không sử dụng tất cả các tính năng mà SGML cung cấp.

DOMDocument là XML (chứ không phải SGML), điều này không thực sự tương thích.

Next để vấn đề đó, xin vui lòng xem 2.2 Mở Exchange Headers Financial trong Ofexfin1.doc nó giải thích với bạn rằng

Nội dung của một tập tin Mở Exchange tài chính bao gồm một tập hợp đơn giản của tiêu đề tiếp theo nội dung xác định bởi tiêu đề mà

và thêm vào:

Một dòng trống sau cuối cùng tiêu đề. Sau đó (đối với loại OFXSGML), dữ liệu có thể đọc được SGML bắt đầu bằng thẻ < OFX>.

Vì vậy, hãy tìm dòng trống đầu tiên và ngắt từng dải cho đến khi có. Sau đó tải phần SGML vào DOMDocument bằng cách chuyển đổi SGML vào XML đầu tiên:

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

mã Ví dụ này sau đó kết quả đầu ra như sau (tái định dạng) XML đó cũng cho thấy rằng DOMDocument nạp dữ liệu đúng cách:

<?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> 

Tôi không biết liệu điều này có thể được xác thực đối với DTD hay không. Có lẽ điều này hoạt động. Ngoài ra nếu SGML không được viết bằng các giá trị của một thẻ trên cùng một dòng (và chỉ một phần tử duy nhất trên mỗi dòng là bắt buộc), thì chuyển đổi mong manh này sẽ bị phá vỡ.

+0

Cảm ơn bạn, nó hoạt động. Nó được chuyển đổi thành mảng php với http://www.bin-co.com/php/scripts/xml2array/ –

+0

định dạng có vẻ hơi phẳng. bạn có thể muốn sử dụng biến thể này: http://stackoverflow.com/a/15729905/367456 - đó là một dòng mã. – hakre

1

Phân tích cú pháp OFX đơn giản nhất thành một mảng với quyền truy cập dễ dàng vào tất cả các giá trị và giao dịch.

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; 
} 
Các vấn đề liên quan