🍣

XML to CSV に変換するスクリプト(Node.js)

2023/01/09に公開

概要

xmlファイルをCSVファイルに変換できるスクリプトです。

使いたい人はgithubから取得してREADME.mdを読んで、それぞれの設定項目を変更して使ってください。(機密情報は含んでいないです。)

https://github.com/Kisukeyas/xml2csv

中で使用しているサンプルxmlは下記サイトから拝借

https://docs.microsoft.com/ja-jp/dotnet/standard/linq/sample-xml-file-multiple-purchase-orders

実装

  1. xmlファイルを読み込む

    https://nodejs.org/api/fs.html

  2. xmldomモジュールを使ってxmlをパース(変換)して、XMLや HTMLソースコードを文字列から DOM のDocumentに解釈した。

  3. (xmlファイルの値を取得できるようにした)

https://developer.mozilla.org/ja/docs/Web/API/DOMParser

  1. 取得したい値を指定して、配列に入れて並び替える

    パスの指定の仕方が独特なので注意 下記参照

https://qiita.com/rllllho/items/cb1187cec0fb17fc650a

https://www.w3schools.com/xml/xpath_syntax.asp

https://nodejs.keicode.com/nodejs/how-to-read-xml.php

  1. 配列→csvに変換し任意の文字コードで出力する

    https://github.com/adaltas/node-csv

コード下記します(sample.js)

const xpath = require('xpath');
const dom = require('xmldom').DOMParser;
const fs = require('fs');
const csv = require('csv');
const iconv = require('iconv-lite');

// 設定項目1
const config = {
    // 読み込みたいxmlファイルのPathを指定
    inputFilePath: "./text.xml",
    // 出力したい先のPathを指定
    outputFilePath: "./text.csv",
    // 出力したい文字コードに設定
    encode: "Shift_JIS",
    // csvの1行目の項目を書く
    csvHeader: ["オーダーNo", "送付先お名前", "請求先お名前"],
    // xmlnsがある場合はURLを記述
    xmlns: ""
}

// xmlファイル読み込み
const xml = fs.readFileSync(config.inputFilePath, "utf8");
const xmlDom = new dom().parseFromString(xml);
const select = xpath.useNamespaces({"xmlns": config.xmlns});

// 設定項目2 取ってきたい値のパスを指定
const xmlPath = {
    purchaseOrderRoot: "xmlns:PurchaseOrders/xmlns:PurchaseOrder",
    shippingAddress: "xmlns:Address[@Type='Shipping']/xmlns:",
    billingAddress: "xmlns:Address[@Type='Billing']/xmlns:",
    
};

const purchaseOrderDataMap = {   
    // OrderNumber
    purchaseOrderNumber: "@PurchaseOrderNumber",
    // Shipping Name
    shippingName: `${xmlPath.shippingAddress}Name/`,
    // Blling Name
    billingName: `${xmlPath.billingAddress}Name/`,
};

let csvRecord = [];

// csvの項目を記述
csvRecord.push(config.csvHeader);

const purchaseOrderRoot = select(xmlPath.purchaseOrderRoot, xmlDom);

for(const purchaseOrder of purchaseOrderRoot) {
    const purchaseOrderNumber = select(`string(${purchaseOrderDataMap.purchaseOrderNumber})`, purchaseOrder);
    const shippingName = select(`string(${purchaseOrderDataMap.shippingName}/text())`, purchaseOrder);
    const billingName = select(`string(${purchaseOrderDataMap.billingName}/text())`, purchaseOrder);

    // csvの項目順に合わせる
    csvRecord.push([purchaseOrderNumber, shippingName, billingName]);
}

console.log(csvRecord)

// csvファイルを書き出し
csv.stringify(csvRecord, function(err, output) {
    // 書き出し文字コードをShift_JISに変更(文字化け対策)
    const changeCharacCode = iconv.encode(output, config.encode);
    fs.writeFileSync(config.outputFilePath, changeCharacCode);
});

Discussion