xmlbuilder vs xmldom vs libxmljs vs fast-xml-parser vs libxmljs2 vs sax vs xml2js
フロントエンド開発におけるXMLパース・生成ライブラリの選択ガイド
xmlbuilderxmldomlibxmljsfast-xml-parserlibxmljs2saxxml2js類似パッケージ:

フロントエンド開発におけるXMLパース・生成ライブラリの選択ガイド

fast-xml-parserlibxmljslibxmljs2saxxml2jsxmlbuilderxmldom は、JavaScript環境でXMLデータを扱うための代表的なnpmパッケージです。これらのライブラリは、XMLのパース(解析)、構築、操作といった異なる用途に特化しており、実行環境(Node.js vs ブラウザ)、パフォーマンス要件、API設計の好み、依存関係の有無などによって適切な選択が変わります。たとえば、軽量で純粋なJavaScript実装を求める場合は fast-xml-parsersax が向いており、DOM準拠の操作が必要なら xmldom を検討します。一方、Node.js専用で高速処理が求められるケースではネイティブバインディングを使う libxmljs 系が有力ですが、ビルドや互換性の課題も考慮する必要があります。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
xmlbuilder41,435,406927-76年前MIT
xmldom1,711,959444-505年前MIT
libxmljs66,0491,06217.7 MB692年前MIT
fast-xml-parser03,053800 kB591日前MIT
libxmljs2087.22 MB299ヶ月前MIT
sax01,14657.1 kB9611日前BlueOak-1.0.0
xml2js04,9733.44 MB2473年前MIT

XMLを扱うJavaScriptライブラリ:パースと生成のベストチョイス

フロントエンド開発においてXMLを扱う機会は減っているとはいえ、レガシーシステム連携や特定業界(医療、物流など)では依然として必要です。しかし、一口に「XMLライブラリ」と言っても、パース専用生成専用DOM操作対応ストリーム処理など、目的によって適切な選択肢は大きく異なります。この記事では、7つの主要npmパッケージを実際のコードとともに比較し、現場で迷わない判断基準を示します。

📥 パース方式の違い:DOM vs ストリーム vs JSON変換

XMLを「読み込む」方法には主に3つのアプローチがあります。それぞれのライブラリがどの方式を採用しているかを確認しましょう。

DOMベース(メモリ上にツリーを構築)

libxmljslibxmljs2xmldom は、XML全体をメモリ上にDOMツリーとして展開します。これはブラウザの DOMParser に似ており、要素の検索や変更が容易ですが、巨大なXMLではメモリを圧迫します。

// xmldom: W3C DOM API準拠
import { DOMParser } from 'xmldom';
const doc = new DOMParser().parseFromString('<book><title>JS Guide</title></book>', 'text/xml');
console.log(doc.getElementsByTagName('title')[0].textContent); // "JS Guide"

// libxmljs: Node.js専用DOM
const libxmljs = require('libxmljs');
const xmlDoc = libxmljs.parseXml('<book><title>JS Guide</title></book>');
console.log(xmlDoc.get('//title').text()); // "JS Guide"

ストリームベース(イベント駆動)

sax はXMLを1文字ずつ読み込み、タグの開始・終了などのイベントを発火します。メモリ使用量は一定で、巨大ファイルにも対応可能ですが、使い方が低レベルです。

// sax: イベント駆動
const sax = require('sax');
const parser = sax.parser(false);
let currentTag = '';
parser.ontext = (text) => {
  if (currentTag === 'title') console.log(text); // "JS Guide"
};
parser.onopentag = (node) => { currentTag = node.name; };
parser.onclosetag = () => { currentTag = ''; };
parser.write('<book><title>JS Guide</title></book>').close();

JSON変換(シンプルなオブジェクトへ)

fast-xml-parserxml2js はXMLをJavaScriptオブジェクト(またはJSON)に変換します。DOMほど柔軟ではありませんが、扱いやすさが魅力です。

// fast-xml-parser: 同期API
import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser();
const obj = parser.parse('<book><title>JS Guide</title></book>');
console.log(obj.book.title); // "JS Guide"

// xml2js: コールバック/Promise
const xml2js = require('xml2js');
xml2js.parseString('<book><title>JS Guide</title></book>', (err, result) => {
  console.log(result.book.title[0]); // "JS Guide"
});

✍️ XML生成:プログラムでXMLを作る

XMLを「書き出す」必要がある場合、xmlbuilder が最も使いやすい選択肢です。他のライブラリはパース専用で、生成機能を持っていません。

// xmlbuilder: チェーン可能なAPI
import { create } from 'xmlbuilder';
const xml = create({ version: '1.0' })
  .ele('book')
    .ele('title').txt('JS Guide').up()
  .end({ pretty: true });
console.log(xml);
// <?xml version="1.0"?>
// <book>
//   <title>JS Guide</title>
// </book>

libxmljsxmldom でも要素を追加して文字列化できますが、APIが冗長で可読性に劣ります。

// libxmljsでの生成(冗長)
const doc = libxmljs.Document();
const book = doc.node('book');
book.node('title', 'JS Guide');
console.log(doc.toString());

// xmldomでの生成(さらに冗長)
const dom = new DOMImplementation().createDocument(null, 'book');
const title = dom.createElement('title');
title.textContent = 'JS Guide';
dom.documentElement.appendChild(title);
console.log(new XMLSerializer().serializeToString(dom));

⚙️ 実行環境と依存関係:フロントエンド向きか?

ライブラリブラウザ対応Node.js専用依存関係ビルド必要
fast-xml-parserなし
saxなし
xml2js✅(バンドル時)少量
xmlbuilderなし
xmldomなし
libxmljslibxml2(ネイティブ)
libxmljs2libxml2(ネイティブ)

ポイント

  • フロントエンド(React/Vueアプリなど)で使うならlibxmljs/libxmljs2 は完全に除外してください。ネイティブモジュールのためブラウザで動作しません。
  • ElectronやNW.jsなど、Node.js統合環境でもネイティブモジュールのビルドが複雑になるため、可能なら純JS製を選んでください。
  • バンドルサイズが気になるSPAでは、fast-xml-parsersax が軽量でおすすめです。

🧪 実用的な比較:よくあるユースケース別

ケース1: APIから受け取ったXMLをJSONに変換して表示したい

fast-xml-parser が最適。同期APIでシンプル、軽量、ブラウザ対応。

// Reactコンポーネント内
import { XMLParser } from 'fast-xml-parser';

function BookList() {
  const [books, setBooks] = useState([]);
  useEffect(() => {
    fetch('/api/books.xml')
      .then(res => res.text())
      .then(xml => {
        const parser = new XMLParser();
        const data = parser.parse(xml);
        setBooks(data.books.book);
      });
  }, []);
}

ケース2: 1GBのXMLログファイルを逐次処理してエラー行を抽出したい

sax 一択。ストリーム処理でメモリを圧迫せず、必要な部分だけを処理できます。

// Node.js スクリプト
const fs = require('fs');
const sax = require('sax');

const parser = sax.createStream(false);
parser.on('opentag', (node) => {
  if (node.name === 'error' && node.attributes.level === 'critical') {
    console.log('Critical error found!');
  }
});
fs.createReadStream('huge-log.xml').pipe(parser);

ケース3: レガシーなJavaシステムと連携するため、DOM API準拠の操作が必要

xmldom を選択document.getElementByIdgetElementsByTagName といったお馴染みのメソッドが使えます。

// テストコードでDOM操作を再現
import { DOMParser } from 'xmldom';

const xml = `<config><server id="main">example.com</server></config>`;
const doc = new DOMParser().parseFromString(xml, 'text/xml');
const server = doc.getElementById('main'); // 動作!

ケース4: 設定ファイルやSitemapをプログラムで生成したい

xmlbuilder が圧倒的に楽。可読性が高く、ミスが起きにくいです。

// Sitemap生成
import { create } from 'xmlbuilder';

const urls = ['/home', '/about'];
const sitemap = create({ version: '1.0', encoding: 'UTF-8' })
  .ele('urlset', { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' });

urls.forEach(url => {
  sitemap.ele('url').ele('loc').txt(`https://example.com${url}`).up().up();
});

fs.writeFileSync('sitemap.xml', sitemap.end({ pretty: true }));

⚠️ 非推奨・注意点

  • xml2js は歴史的経緯で広く使われていますが、パフォーマンスとAPI設計の面で現代的とは言えません。新規プロジェクトでは fast-xml-parser を優先してください。
  • libxmljs / libxmljs2 はNode.js v18+やApple Silicon環境でビルドエラーが頻発します。どうしても必要なら、Dockerイメージや事前ビルド済みバイナリの利用を検討する必要があります。
  • xmldom は公式に @xmldom/xmldom に移行されています。古い xmldom パッケージは非推奨なので、新規プロジェクトでは新しいパッケージ名を使用してください。

📊 まとめ:選択フロー

  1. XMLを「生成」する必要がある?xmlbuilder
  2. XMLを「パース」する必要がある?
    • 巨大ファイル or メモリ節約が必須?sax
    • DOM操作(getElementsByTagNameなど)が必要?@xmldom/xmldom
    • 単純にJSONに変換したい?
      • フロントエンド or 軽量さ重視?fast-xml-parser
      • Node.js専用で超高速が必要?libxmljs2(ビルド覚悟で)
    • レガシーなコードで xml2js が使われている? → 維持可だが新規には非推奨

これらのライブラリは目的が明確に分かれているため、「どれが一番良い」というより「どのタスクに最適か」で選ぶのが正解です。あなたのプロジェクトの要件に合った1つを選びましょう。

選び方: xmlbuilder vs xmldom vs libxmljs vs fast-xml-parser vs libxmljs2 vs sax vs xml2js

  • xmlbuilder:

    xmlbuilder はXMLをプログラムで構築(生成)することに特化したライブラリです。チェーン可能なAPIで可読性が高く、名前空間やDOCTYPEなどの高度な機能もサポートしています。XMLを出力する必要がある場合(例:APIレスポンス、設定ファイル生成)に非常に有用です。ただし、パース機能は持たないため、読み込みと書き込みの両方が必要な場合は他のパーサーと組み合わせる必要があります。

  • xmldom:

    xmldom はブラウザのDOM API(Document、Elementなど)に準拠したXML DOM実装をNode.jsやブラウザで提供します。W3C標準に近いインターフェースで操作できるため、既存のDOM操作コードを再利用しやすいのが利点です。ただし、パフォーマンスは純JSパーサーより劣ることが多く、大規模データには不向きです。DOM互換性が必須のレガシーシステム統合やテスト環境での使用に適しています。

  • libxmljs:

    libxmljs はlibxml2のNode.jsバインディングで、高速かつ堅牢なXML処理を提供しますが、ネイティブアドオンに依存するためビルド環境が必要です。Node.js専用で、大規模なXMLファイルを高速に処理したいサーバーサイドアプリケーションに向いています。ただし、ElectronやDocker環境でのビルド問題が発生しやすく、フロントエンドやCI/CD環境が制限されるケースでは避けるべきです。

  • fast-xml-parser:

    fast-xml-parser は純粋なJavaScriptで書かれた高速なXMLパーサーで、ブラウザとNode.jsの両方で動作します。依存関係がなく軽量で、JSONへの変換やバリデーション機能も備えています。新しいプロジェクトでXMLを読み込む必要があり、特にDOM操作が不要な場合やバンドルサイズを抑えたいフロントエンド向けアプリに最適です。ただし、W3C DOM APIには非準拠なので、DOM互換性が必要なケースには向きません。

  • libxmljs2:

    libxmljs2libxmljs のフォークで、より新しいNode.jsバージョンやlibxml2の機能に対応しています。基本的な使い方は libxmljs とほぼ同じですが、メンテナンス状況や互換性が若干異なります。libxmljs でビルドエラーが発生する場合の代替として検討できますが、依然としてネイティブ依存がある点は変わりません。新規プロジェクトでは、まず純JS製の選択肢を検討し、それでも性能が足りない場合に限って導入を検討すべきです。

  • sax:

    sax はストリーム指向のイベント駆動型XMLパーサーで、メモリ効率が非常に高く、巨大なXMLファイルを逐次処理する必要がある場合に最適です。ブラウザとNode.jsの両方で動作し、依存関係がありません。ただし、使い方が低レベルで、DOMツリーを自動構築しないため、手動で状態管理が必要です。シンプルなタグ抽出やフィルタリングなど、部分的な処理に特化したユースケースで力を発揮します。

  • xml2js:

    xml2js は古くから使われているXML→JavaScriptオブジェクト変換ライブラリで、コールバックベースのAPIを提供します(Promise対応も可能)。使い方は直感的ですが、パフォーマンスやメモリ使用量の面で現代的な選択肢とは言えません。既存コードベースで使われている場合は維持してもよいですが、新規プロジェクトではより高速で軽量な fast-xml-parser を優先すべきです。

xmlbuilder のREADME

xmlbuilder-js

An XML builder for node.js similar to java-xmlbuilder.

License NPM Version NPM Downloads

Travis Build Status AppVeyor Build status Dev Dependency Status Code Coverage

Announcing xmlbuilder2:

The new release of xmlbuilder is available at xmlbuilder2! xmlbuilder2 has been redesigned from the ground up to be fully conforming to the modern DOM specification. It supports XML namespaces, provides built-in converters for multiple formats, collection functions, and more. Please see upgrading from xmlbuilder in the wiki.

New development will be focused towards xmlbuilder2; xmlbuilder will only receive critical bug fixes.

Installation:

npm install xmlbuilder

Usage:

var builder = require('xmlbuilder');

var xml = builder.create('root')
  .ele('xmlbuilder')
    .ele('repo', {'type': 'git'}, 'git://github.com/oozcitak/xmlbuilder-js.git')
  .end({ pretty: true});

console.log(xml);

will result in:

<?xml version="1.0"?>
<root>
  <xmlbuilder>
    <repo type="git">git://github.com/oozcitak/xmlbuilder-js.git</repo>
  </xmlbuilder>
</root>

It is also possible to convert objects into nodes:

var builder = require('xmlbuilder');

var obj = {
  root: {
    xmlbuilder: {
      repo: {
        '@type': 'git', // attributes start with @
        '#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
      }
    }
  }
};

var xml = builder.create(obj).end({ pretty: true});
console.log(xml);

If you need to do some processing:

var builder = require('xmlbuilder');

var root = builder.create('squares');
root.com('f(x) = x^2');
for(var i = 1; i <= 5; i++)
{
  var item = root.ele('data');
  item.att('x', i);
  item.att('y', i * i);
}

var xml = root.end({ pretty: true});
console.log(xml);

This will result in:

<?xml version="1.0"?>
<squares>
  <!-- f(x) = x^2 -->
  <data x="1" y="1"/>
  <data x="2" y="4"/>
  <data x="3" y="9"/>
  <data x="4" y="16"/>
  <data x="5" y="25"/>
</squares>

See the wiki for details and examples for more complex examples.