function read_csv($out, $in_file, $options = array()) { if (!isset($options["enclosure"])) { $options["enclosure"] = '"'; } $enclosure = $options["enclosure"]; $delimiter = $options["delimiter"]; // CSVファイルを正規化する。 $tmp = tmpfile(); if (($in = fopen($in_file, "r")) === false) { fputs(STDERR, "Error[{$in_file}]: Failed to open the file.\n"); return; } while (($line = fgets($in)) !== false) { // UTF-8にする。 $line = normalize_encoding($line); // 全角カタカナ、半角英数字、PHP_EOL、NFCにする。 $line = normalize_string($line); fputs($tmp, $line); } fclose($in); fflush($tmp); rewind($tmp); // ワークシートの先頭行に "# ファイル名" を出力する。 $filename = pathinfo($in_file, PATHINFO_FILENAME); $ext = pathinfo($in_file, PATHINFO_EXTENSION); $filename_fragments = explode(".", $filename); $worksheet_name = $filename_fragments[count($filename_fragments) - 1]; fputs($out, "# {$worksheet_name}\n"); $headers = explode(":", "^:" . $options["inheader"] . ":\$"); while (($csv_record = fgetcsv($tmp, 65536, $delimiter, $enclosure)) !== FALSE) { for ($i = 0; $i < count($csv_record); $i++) { $csv_record[$i] = trim($csv_record[$i]); } if (($header = array_shift($headers)) !== null) { if ($header == "^") { $num_cols = count($csv_record); $fields = array_fill(0, $num_cols, ""); $types = array_fill(0, $num_cols, "text"); $params = array_fill(0, $num_cols, ""); $titles = array_fill(0, $num_cols, ""); $header = array_shift($headers); } if ($header == "F") { $fields = array_replace($fields, $csv_record); } else { if ($header == "C") { $types = array_replace($types, $csv_record); } else { if ($header == "P") { $params = array_replace($params, $csv_record); } else { if ($header == "T") { $titles = array_replace($titles, $csv_record); } else { if ($header == "N") { } else { if ($header == "\$") { for ($i = 0; $i < count($fields); $i++) { if ($fields[$i] == "") { $fields[$i] = $titles[$i]; } if ($fields[$i] == "") { $fields[$i] = "f{$i}"; $titles[$i] = "f{$i}"; } } array_unshift($fields, "fields"); fputcsv($out, $fields, ",", '"'); array_unshift($types, "types"); fputcsv($out, $types, ",", '"'); array_unshift($params, "params"); fputcsv($out, $params, ",", '"'); array_unshift($titles, "titles"); fputcsv($out, $titles, ",", '"'); $headers = array(); // (最初の)データを出力する。 array_unshift($csv_record, "record"); fputcsv($out, $csv_record, ",", '"'); } } } } } } } else { // データを出力する。 array_unshift($csv_record, "record"); fputcsv($out, $csv_record, ",", '"'); } } // ワークシートの最終行に空行を出力する。 fputs($out, "\n"); fclose($tmp); return; }
function read_yaml($out, $in_file, $options = array()) { // YAMLオブジェクトを読む。 $contents = file_get_contents($in_file); $contents = normalize_encoding($contents); $contents = normalize_string($contents); // parse yaml, '0' for the first document if (($dataset = yaml_parse($contents, 0)) === FALSE) { fputs(STDERR, "Error[{$in_file}]: The file is not valid format.\n"); return; } if (!is_array($dataset)) { fputs(STDERR, "Error[{$in_file}]: The 1st level is not an object.\n"); } foreach ($dataset as $worksheet_name => $worksheet) { if (!is_array($worksheet)) { fputs(STDERR, "Error[{$in_file}]: The 2nd level is not an array.\n"); return; } // Pass1: ヘッダとフィールド名を収集する。 $fields = array(); $titles = array(); $types = array(); $params = array(); $records = array(); $num_cols = 0; if ($worksheet["titles"] !== null) { $titles = array_values($worksheet["titles"]); $fields += array_keys($worksheet["titles"]); } if ($worksheet["types"] !== null) { $types = array_values($worksheet["types"]); $fields += array_keys($worksheet["types"]); } if ($worksheet["params"] !== null) { $params = array_values($worksheet["params"]); $fields += array_keys($worksheet["params"]); } if ($worksheet["records"] !== null) { $records = array_values($worksheet["records"]); for ($row = 0; $row < count($records); $row++) { $fields += array_keys($records[$row]); } } if (($num_cols = count($fields)) == 0) { fputs(STDERR, "Error[{$in_file}]: No field specidied.\n"); return; } // Pass2: 内部形式CSVを出力する。 // 先頭行に "# ファイル名" を出力する。 fputs($out, "# {$worksheet_name}\n"); // ヘッダ行を出力する。 $fields = array_pad($fields, $num_cols, ""); array_unshift($fields, "fields"); fputcsv($out, $fields, ",", '"'); $types = array_pad($types, $num_cols, "text"); array_unshift($types, "types"); fputcsv($out, $types, ",", '"'); $params = array_pad($params, $num_cols, ""); array_unshift($params, "params"); fputcsv($out, $params, ",", '"'); $titles = array_pad($titles, $num_cols, ""); array_unshift($titles, "titles"); fputcsv($out, $titles, ",", '"'); // データ行を出力する。 for ($row = 0; $row < count($records); $row++) { $record = $records[$row]; $csv_record = array(); // $fields は上で unshift しているので 1 から開始する。 for ($col = 1; $col < count($fields); $col++) { $csv_record[$col] = $record[$fields[$col]]; } array_unshift($csv_record, "record"); fputcsv($out, $csv_record, ",", '"'); } // 最終行に空行を出力する。 fputs($out, "\n"); } return; }
function read_xml($out, $in_file, $options = array()) { // XMLオブジェクトを読む。 $contents = normalize_encoding(file_get_contents($in_file)); $contents = normalize_string($contents); $dom = new DOMDocument("1.0", "UTF-8"); $dom->loadXML($contents); // 第1レベル要素(ルート)を取得する。固定名(dataset)でなくても受理する。 $node1 = $dom->documentElement; for ($i = 0; $i < $node1->childNodes->length; $i++) { // 第2レベル要素(ワークシート)を取得する。 $node2 = $node1->childNodes->item($i); if (!$node2 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $worksheet_name = (string) $node2->tagName; // Pass1: ヘッダとフィールド名を収集する。 $titles = array(); $types = array(); $params = array(); $records = array(); for ($j = 0; $j < $node2->childNodes->length; $j++) { // 第3レベル要素(オブジェクト)を取得する。 $node3 = $node2->childNodes->item($j); if (!$node3 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $object_name = (string) $node3->tagName; switch ($object_name) { case "titles": for ($k = 0; $k < $node3->childNodes->length; $k++) { // 第4レベル要素(フィールド)を取得する。 $node4 = $node3->childNodes->item($k); if (!$node4 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $field = (string) $node4->tagName; $value = (string) $node4->nodeValue; $titles[$field] = $value; } break; case "types": for ($k = 0; $k < $node3->childNodes->length; $k++) { // 第4レベル要素(フィールド)を取得する。 $node4 = $node3->childNodes->item($k); if (!$node4 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $field = (string) $node4->tagName; $value = (string) $node4->nodeValue; $types[$field] = $value; } break; case "params": for ($k = 0; $k < $node3->childNodes->length; $k++) { // 第4レベル要素(フィールド)を取得する。 $node4 = $node3->childNodes->item($k); if (!$node4 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $field = (string) $node4->tagName; $value = (string) $node4->nodeValue; $params[$field] = $value; } break; case "records": for ($k = 0; $k < $node3->childNodes->length; $k++) { // 第4レベル要素(レコード)を取得する。 $node4 = $node3->childNodes->item($k); if (!$node4 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $record = array(); for ($l = 0; $l < $node4->childNodes->length; $l++) { // 第5レベル要素(フィールド)を取得する。 $node5 = $node4->childNodes->item($l); if (!$node5 instanceof DOMElement) { continue; } // タグ間の改行は無視する。 $field = (string) $node5->tagName; $value = (string) $node5->nodeValue; $record[$field] = $value; } $records[] = $record; // $k はインデックスに使わないこと。 } break; } } $fields = array(); $num_cols = 0; $fields += array_keys($titles); $fields += array_keys($types); $fields += array_keys($params); for ($row = 0; $row < count($records); $row++) { $fields += array_keys($records[$row]); } if (($num_cols = count($fields)) == 0) { fputs(STDERR, "Error[{$in_file}]: no field specidied.\n"); return; } // Pass2: 内部形式CSVを出力する。 // 先頭行に "# ファイル名" を出力する。 fputs($out, "# {$worksheet_name}\n"); // ヘッダ行を出力する。 $fields = array_pad($fields, $num_cols, ""); array_unshift($fields, "fields"); fputcsv($out, $fields, ",", '"'); $types = array_pad($types, $num_cols, "text"); array_unshift($types, "types"); fputcsv($out, $types, ",", '"'); $params = array_pad($params, $num_cols, ""); array_unshift($params, "params"); fputcsv($out, $params, ",", '"'); $titles = array_pad($titles, $num_cols, ""); array_unshift($titles, "titles"); fputcsv($out, $titles, ",", '"'); // データ行を出力する。 for ($row = 0; $row < count($records); $row++) { $record = $records[$row]; $csv_record = array(); // $fields は上で unshift しているので 1 から開始する。 for ($col = 1; $col < count($fields); $col++) { $csv_record[$col] = $record[$fields[$col]]; } array_unshift($csv_record, "record"); fputcsv($out, $csv_record, ",", '"'); } // 最終行に空行を出力する。 fputs($out, "\n"); } return; }