📄 Node-RED XML ノード完全ガイド

📚 目次

📖 1. 概要

XML ノードは、XML文字列とJavaScriptオブジェクトを相互変換するノードです。XML形式のデータを扱うAPIやファイルとの連携に使用します。

📚 翻訳者に例えると:XML ノードは2つの言語(XML形式とJavaScriptオブジェクト形式)を相互に翻訳する通訳者のようなものです。どちらの形式でデータを受け取っても、もう一方の形式に変換してくれます。

XML文字列 XML オブジェクト

💡 ポイント:

⚙️ 2. 設定詳細

プロパティ

プロパティ説明デフォルト
名前ノードの名前
プロパティ変換対象のプロパティmsg.payload
XMLタグ属性を次のプロパティ名として表現XML属性を格納するプロパティ名$ (デフォルト)
文字列を参照するための接頭辞テキストコンテンツを格納するプロパティ名_ (デフォルト)

🔄 3. 変換ルール

XML → オブジェクト変換

入力(XML)

<person id="1"> <name>田中太郎</name> <age>30</age> </person>

出力(オブジェクト)

{ "person": { "$": { "id": "1" }, "name": ["田中太郎"], "age": ["30"] } }

オブジェクト → XML変換

入力(オブジェクト)

{ "book": { "$": { "isbn": "123" }, "title": "Node-RED入門", "price": 2000 } }

出力(XML)

<?xml version="1.0"?> <book isbn="123"> <title>Node-RED入門</title> <price>2000</price> </book>

属性とテキストの表現

XML要素オブジェクト表現
属性 <tag attr="value">{ "$": { "attr": "value" } }
テキスト <tag>text</tag>{ "tag": ["text"] } または { "_": "text" }
属性+テキスト{ "$": { "attr": "v" }, "_": "text" }

🔧 4. 実用的な使用パターン

📥 サンプルフローのインポート方法:

  1. 下のサンプルフローJSONをコピー
  2. Node-REDエディタで メニュー → 読み込み を選択
  3. JSONをペーストして「読み込み」をクリック

このサンプルフローには、以下で説明するパターンの実例が含まれています。

📥 サンプルフローJSON(クリックで展開)
[ { "id": "xml_sample_tab", "type": "tab", "label": "XML サンプル", "disabled": false, "info": "" }, { "id": "xml_comment1", "type": "comment", "z": "xml_sample_tab", "name": "━━━ XML → オブジェクト変換 ━━━", "info": "", "x": 180, "y": 40, "wires": [] }, { "id": "xml_inject1", "type": "inject", "z": "xml_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 100, "wires": [["xml_template1"]] }, { "id": "xml_template1", "type": "template", "z": "xml_sample_tab", "name": "XML文字列", "field": "payload", "fieldType": "msg", "format": "text", "syntax": "plain", "template": "\n\n \n Node-RED入門\n 山田太郎\n 2500\n \n \n IoT実践ガイド\n 鈴木花子\n 3000\n \n", "output": "str", "x": 290, "y": 100, "wires": [["xml_parse"]] }, { "id": "xml_parse", "type": "xml", "z": "xml_sample_tab", "name": "XML→Obj", "property": "payload", "attr": "", "chr": "", "x": 450, "y": 100, "wires": [["xml_debug1"]] }, { "id": "xml_debug1", "type": "debug", "z": "xml_sample_tab", "name": "オブジェクト出力", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 620, "y": 100, "wires": [] }, { "id": "xml_comment2", "type": "comment", "z": "xml_sample_tab", "name": "━━━ オブジェクト → XML変換 ━━━", "info": "", "x": 180, "y": 180, "wires": [] }, { "id": "xml_inject2", "type": "inject", "z": "xml_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 240, "wires": [["xml_func1"]] }, { "id": "xml_func1", "type": "function", "z": "xml_sample_tab", "name": "オブジェクト生成", "func": "msg.payload = {\n \"order\": {\n \"$\": { \"id\": \"ORD-001\" },\n \"customer\": \"田中商店\",\n \"items\": {\n \"item\": [\n { \"name\": \"商品A\", \"qty\": \"2\" },\n { \"name\": \"商品B\", \"qty\": \"1\" }\n ]\n },\n \"total\": \"5000\"\n }\n};\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 300, "y": 240, "wires": [["xml_build"]] }, { "id": "xml_build", "type": "xml", "z": "xml_sample_tab", "name": "Obj→XML", "property": "payload", "attr": "", "chr": "", "x": 470, "y": 240, "wires": [["xml_debug2"]] }, { "id": "xml_debug2", "type": "debug", "z": "xml_sample_tab", "name": "XML出力", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 620, "y": 240, "wires": [] }, { "id": "xml_comment3", "type": "comment", "z": "xml_sample_tab", "name": "━━━ データ抽出の例 ━━━", "info": "", "x": 160, "y": 320, "wires": [] }, { "id": "xml_inject3", "type": "inject", "z": "xml_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 380, "wires": [["xml_template2"]] }, { "id": "xml_template2", "type": "template", "z": "xml_sample_tab", "name": "センサーXML", "field": "payload", "fieldType": "msg", "format": "text", "syntax": "plain", "template": "\n \n 25.5\n 2024-01-15T10:30:00\n \n \n 60\n 2024-01-15T10:30:00\n \n", "output": "str", "x": 290, "y": 380, "wires": [["xml_parse2"]] }, { "id": "xml_parse2", "type": "xml", "z": "xml_sample_tab", "name": "XML→Obj", "property": "payload", "attr": "", "chr": "", "x": 450, "y": 380, "wires": [["xml_func2"]] }, { "id": "xml_func2", "type": "function", "z": "xml_sample_tab", "name": "温度抽出", "func": "// センサーデータから温度を抽出\nvar sensors = msg.payload.sensors.sensor;\nvar tempSensor = sensors.find(s => s.$.type === \"temperature\");\n\nmsg.payload = {\n sensorId: tempSensor.$.id,\n value: parseFloat(tempSensor.value[0]._),\n unit: tempSensor.value[0].$.unit,\n timestamp: tempSensor.timestamp[0]\n};\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 600, "y": 380, "wires": [["xml_debug3"]] }, { "id": "xml_debug3", "type": "debug", "z": "xml_sample_tab", "name": "温度データ", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload.value", "statusType": "msg", "x": 770, "y": 380, "wires": [] } ]

使用パターン

パターン1: XML → オブジェクト変換

サンプルフローの「XML → オブジェクト変換」を参照してください。

XML文字列 XML→Obj オブジェクト

ポイント:

パターン2: オブジェクト → XML変換

サンプルフローの「オブジェクト → XML変換」を参照してください。

オブジェクト生成 Obj→XML XML文字列

ポイント: 属性をつける場合は $ プロパティを使用

パターン3: データ抽出の例

サンプルフローの「データ抽出の例」を参照してください。

センサーXML XML→Obj 温度抽出 温度データ

ポイント:

📝 5. 演習問題

演習1: 基本的なXML変換 初級

📋 課題: シンプルなXML文字列をオブジェクトに変換してください。

✅ 成功の条件:

💡 ヒント

Template ノードでXML文字列を作成し、XML ノードで変換します。

✅ 解答例フロー
[ {"id": "ex1_tab", "type": "tab", "label": "演習1"}, {"id": "ex1_inject", "type": "inject", "z": "ex1_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 100, "wires": [["ex1_template"]]}, {"id": "ex1_template", "type": "template", "z": "ex1_tab", "name": "XML", "field": "payload", "fieldType": "msg", "format": "text", "syntax": "plain", "template": "山田太郎yamada@example.com", "output": "str", "x": 270, "y": 100, "wires": [["ex1_xml"]]}, {"id": "ex1_xml", "type": "xml", "z": "ex1_tab", "name": "XML→Obj", "property": "payload", "attr": "", "chr": "", "x": 410, "y": 100, "wires": [["ex1_debug"]]}, {"id": "ex1_debug", "type": "debug", "z": "ex1_tab", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 550, "y": 100, "wires": []} ]

演習2: オブジェクトからXML生成 初級

📋 課題: JavaScriptオブジェクトからXML文字列を生成してください。

✅ 成功の条件:

💡 ヒント

Change ノードで JSON 値型を使ってオブジェクトを設定し、XML ノードで変換します。

✅ 解答例フロー
[ {"id": "ex2_tab", "type": "tab", "label": "演習2"}, {"id": "ex2_inject", "type": "inject", "z": "ex2_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 100, "wires": [["ex2_change"]]}, {"id": "ex2_change", "type": "change", "z": "ex2_tab", "name": "オブジェクト", "rules": [{"t": "set", "p": "payload", "pt": "msg", "to": "{\"product\":{\"name\":\"ノートPC\",\"price\":\"98000\",\"stock\":\"15\"}}", "tot": "json"}], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 280, "y": 100, "wires": [["ex2_xml"]]}, {"id": "ex2_xml", "type": "xml", "z": "ex2_tab", "name": "Obj→XML", "property": "payload", "attr": "", "chr": "", "x": 430, "y": 100, "wires": [["ex2_debug"]]}, {"id": "ex2_debug", "type": "debug", "z": "ex2_tab", "name": "XML出力", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 580, "y": 100, "wires": []} ]

演習3: 属性付きXMLの処理 中級

📋 課題: 属性を持つXMLを解析し、属性値を取得してください。

✅ 成功の条件:

💡 ヒント

属性は $ プロパティに格納されます。Change ノードの JSONata 式を使って、ネストしたプロパティから値を抽出できます。

✅ 解答例フロー
[ {"id": "ex3_tab", "type": "tab", "label": "演習3"}, {"id": "ex3_inject", "type": "inject", "z": "ex3_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 100, "wires": [["ex3_template"]]}, {"id": "ex3_template", "type": "template", "z": "ex3_tab", "name": "属性付きXML", "field": "payload", "fieldType": "msg", "format": "text", "syntax": "plain", "template": "\n スマートフォン\n 50000\n", "output": "str", "x": 290, "y": 100, "wires": [["ex3_xml"]]}, {"id": "ex3_xml", "type": "xml", "z": "ex3_tab", "name": "XML→Obj", "property": "payload", "attr": "", "chr": "", "x": 450, "y": 100, "wires": [["ex3_change"]]}, {"id": "ex3_change", "type": "change", "z": "ex3_tab", "name": "属性抽出", "rules": [{"t": "set", "p": "payload", "pt": "msg", "to": "{\n \"id\": payload.item.`$`.id,\n \"category\": payload.item.`$`.category,\n \"name\": payload.item.name[0],\n \"price\": payload.item.price[0].`_`,\n \"currency\": payload.item.price[0].`$`.currency\n}", "tot": "jsonata"}], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 600, "y": 100, "wires": [["ex3_debug"]]}, {"id": "ex3_debug", "type": "debug", "z": "ex3_tab", "name": "抽出結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 750, "y": 100, "wires": []} ]

演習4: 属性付きXMLの生成 上級

📋 課題: 属性を持つXMLをオブジェクトから生成してください。

✅ 成功の条件:

💡 ヒント

属性を設定するには "$": { "attrName": "value" } 形式でオブジェクトを作成します。

✅ 解答例フロー
[ {"id": "ex4_tab", "type": "tab", "label": "演習4"}, {"id": "ex4_inject", "type": "inject", "z": "ex4_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 100, "wires": [["ex4_func"]]}, {"id": "ex4_func", "type": "function", "z": "ex4_tab", "name": "属性付きObj", "func": "msg.payload = {\n \"response\": {\n \"$\": { \"status\": \"success\", \"code\": \"200\" },\n \"data\": {\n \"user\": {\n \"$\": { \"id\": \"U001\" },\n \"name\": \"テストユーザー\"\n }\n }\n }\n};\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 290, "y": 100, "wires": [["ex4_xml"]]}, {"id": "ex4_xml", "type": "xml", "z": "ex4_tab", "name": "Obj→XML", "property": "payload", "attr": "", "chr": "", "x": 450, "y": 100, "wires": [["ex4_debug"]]}, {"id": "ex4_debug", "type": "debug", "z": "ex4_tab", "name": "XML出力", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 600, "y": 100, "wires": []} ]

✅ 6. まとめ

🎯 重要ポイント:

⚠️ 注意事項:

🏭 7. 実務活用例

ケース1: SOAP API連携

SOAP Webサービスとの通信でXMLリクエスト/レスポンスを処理。

ケース2: 設定ファイル管理

XML形式の設定ファイルを読み込み、設定値をフローで使用。

ケース3: レガシーシステム連携

XML形式でデータ交換を行う古いシステムとの連携。

ケース4: RSS/Atomフィード処理

RSSフィードを解析して最新記事を取得・表示。

📚 Node-RED 公式ドキュメント