🐥
JavaScript で XML を扱う | NodeJS + fast-xml-parser
fast-xml-parser
でできること
- XML をオブジェクトに変換する(パース)
- オブジェクトを XML に変換する(ビルド)
- XML のフォーマットを検証する(バリデーション)
前提
- Node: 20.12.2
- fast-xml-parser: ^4.5.0
セットアップ
npm i fast-xml-parser
使い方
XML をオブジェクトに変換する(パース)
index.js
const { XMLParser } = require('fast-xml-parser');
const options = {
ignoreAttributes: false, // 属性値がデフォルトでは無視されてしまうので有効化
};
const parser = new XMLParser(options);
// 以下の XML 文字列を使用する.
const xmlData = `
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>1</id> <name>Widget A</name> <price>25.00</price>
<description>A high-quality widget.</description>
<inStock>true</inStock>
</product>
<product>
<id>2</id> <name>Gadget B</name> <price>15.50</price>
<description>An affordable gadget.</description>
<inStock>false</inStock>
</product>
</catalog>
`;
const outputObject = parser.parse(xmlData);
console.log(outputObject);
上記を実行すると以下のようなオブジェクトが得られる.
{
'?xml': {
'@_version': '1.0',
'@_encoding': 'UTF-8'
},
catalog: {
product: [
{
id: 1, name: 'Widget A', price: 25,
description: 'A high-quality widget.',
inStock: true
},
{
id: 2, name: 'Gadget B', price: 15.5,
description: 'An affordable gadget.',
inStock: false
}
]
}
}
オブジェクトを XML に変換する(ビルド)
index.js
const { XMLBuilder } = require('fast-xml-parser');
const options = {
ignoreAttributes: false, // 属性値がデフォルトでは無視されてしまうので有効化
};
const builder = new XMLBuilder(options);
// 以下のオブジェクトを使用する.
const objectData = {
'?xml': {
'@_version': '1.0',
'@_encoding': 'UTF-8'
},
catalog: {
product: [
{
id: 1, name: 'Widget A', price: 25,
description: 'A high-quality widget.',
inStock: true
},
{
id: 2, name: 'Gadget B', price: 15.5,
description: 'An affordable gadget.',
inStock: false
}
]
}
}
const outputXML = builder.build(objectData);
console.log(outputXML);
上記を実行すると以下のような XML 文字列が得られる.
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>1</id> <name>Widget A</name> <price>25</price>
<description>A high-quality widget.</description>
<inStock>true</inStock>
</product>
<product>
<id>2</id> <name>Gadget B</name> <price>15.5</price>
<description>An affordable gadget.</description>
<inStock>false</inStock>
</product>
</catalog>
XML のフォーマットを検証する(バリデーション)
index.js
const { XMLValidator } = require('fast-xml-parser');
// 以下の XML 文字列を使用する.
// XML 宣言はドキュメントの最初になければならない.
const xmlData = `
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>1</id> <name>Widget A</name> <price>25.00</price>
<description>A high-quality widget.</description>
<inStock>true</inStock>
</product>
<product>
<id>2</id> <name>Gadget B</name> <price>15.50</price>
<description>An affordable gadget.</description>
<inStock>false</inStock>
</product>
</catalog>
`;
const result = XMLValidator.validate(xmlData);
console.log(result);
{
err: {
code: 'InvalidXml',
msg: 'XML declaration allowed only at the start of the document.',
line: 2,
col: 10
}
}
index.js
const { XMLValidator } = require('fast-xml-parser');
// 以下の XML 文字列を使用する.
// XML 宣言はドキュメントの最初になければならない.
const xmlData = `<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>1</id> <name>Widget A</name> <price>25.00</price>
<description>A high-quality widget.</description>
<inStock>true</inStock>
</product>
<product>
<id>2</id> <name>Gadget B</name> <price>15.50</price>
<description>An affordable gadget.</description>
<inStock>false</inStock>
</product>
</catalog>
`;
const result = XMLValidator.validate(xmlData);
console.log(result);
true
index.js
const { XMLValidator } = require('fast-xml-parser');
// 以下の XML 文字列を使用する.
// inStock の閉じタグがない.
const xmlData = `<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<product>
<id>1</id> <name>Widget A</name> <price>25.00</price>
<description>A high-quality widget.</description>
<inStock>true</inStock>
</product>
<product>
<id>2</id> <name>Gadget B</name> <price>15.50</price>
<description>An affordable gadget.</description>
<inStock>false<inStock>
</product>
</catalog>
`;
const result = XMLValidator.validate(xmlData);
console.log(result);
{
err: {
code: 'InvalidXml',
msg: 'XML declaration allowed only at the start of the document.',
line: 2,
col: 10
}
}
XMLValidator には、以下のようにオプションを指定できる.
const result = XMLValidator.validate(xmlData, options);
代表的なオプションは unpairedTags
.
閉じタグを持たないタグを指定できる. 例えば <br>
.
XMLParser, XMLBuilder, XMLValidator でこのオプションが使用可能.
const xmlData = `<parent><extra></parent>`;
const options = {
unpairedTags: ['extra'],
}
const result = XMLValidator.validate(xmlData, options);
なお、XMLValidator はエラー時、エラーを投げるので、try catch
などが使用可能である.
主なオプション
ignoreAttributes
属性値(<a xx="this is attr">
)を無視する. デフォルトは true
.
ignoreAttributes: false
attributeNamePrefix
ignoreAttributes
オプションを false
にしたときの、属性のキーにつけるプレフィックス.
デフォルトは @_
. XMLParser, XMLBuilder で使用可能.
attributeNamePrefix : '@_'
// <aaa xxx="nice">wow</aaa> -> { '@_xxx': 'nice', aaa: 'wow' }
allowBooleanAttributes
値を持たない属性を許可する. true
にしたとき、属性=true
として扱われる.
デフォルトは false
. XMLParser, XMLBuilder で使用可能.
allowBooleanAttributes: true
// <aaa checked>wow</aaa> -> { '@_checked': true, aaa: 'wow' }
allowBooleanAttributes: false
// <aaa checked>wow</aaa> -> { aaa: 'wow' }
alwaysCreateTextNode
テキストノードが存在するとき、常にテキストノード(#text
)を作成する. デフォルトは false
.
alwaysCreateTextNode: false
// <a>wow <b>hello</b> </a> -> { a: { b: 'hello', '#text': 'wow' }
alwaysCreateTextNode: true
// <a>wow <b>hello</b> </a>
// -> { a: { b: { '#text': 'hello' }, '#text': 'wow' } }
isArray
タグを配列とオブジェクトのどちらでパースするかを指定する. 関数を取り、戻り値が true
なら配列として、false
ならオブジェクトとしてパースされる.
index.js
const alwaysArray = [
'a.b',
];
const options = {
isArray: (tagName, tagPath, isLeafNode, isAttribute) => {
console.log(tagName, tagPath, isLeafNode, isAttribute);
return (alwaysArray.indexOf(tagPath) !== -1);
}
};
const xmlData = `<a><b>hello</b></a>`;
const result = (new XMLParser(options)).parse(xmlData);
console.log(result);
アウトプットは以下.
b a.b true undefined
a a false undefined
{ a: { b: [ 'hello' ] } }
その他のオプション、詳しい説明は以下のドキュメントを参照
Discussion