
你好,我是翔宇,很高兴能和大家一起探索 n8n 这个强大的自动化工具。在使用 n8n 的过程中积累了一些经验,特别是对于那些刚接触自动化、没有编程基础的朋友们,我希望能通过这篇深度教程,帮助大家彻底搞懂 n8n 中几个非常实用但也容易混淆的核心节点:HTML、Markdown 和 XML 节点。
这三个节点处理的是我们在网络世界中无处不在的三种标记语言。理解它们,意味着你能更自如地从网页抓取信息、格式化文本内容、与各种网络服务和老系统打交道。别担心,虽然听起来有点“技术”,但我会用最通俗易懂的方式,结合我的实践经验,带你一步步掌握它们。
本教程将分为三个主要部分,分别深入解析 HTML、Markdown 和 XML 节点。每一部分都会包含:
- 节点概览:这是什么?为什么你需要它?
- 参数配置详解:每个选项都是做什么用的?怎么设置?
- 数据映射与流转:数据如何流入节点?又如何流出?
- 翔宇工作流实战:在实际场景中如何应用?
- 常见报错与解决方案:遇到问题怎么办?
- 注意事项与最佳实践:有哪些坑需要避开?
准备好了吗?让我们一起进入 n8n 的自动化世界,解锁处理网页、文本和结构化数据的超能力!
第一部分:HTML 节点深度解析
HTML (HyperText Markup Language) 是构建网页的基础。我们浏览的每一个网页,其骨架都是由 HTML 搭建的。n8n 的 HTML 节点,就是我们与这些网页结构进行交互的利器。无论是想从网页上“抠”下特定信息(比如商品价格、新闻标题),还是想自己生成一段 HTML 代码用于邮件或报告,HTML 节点都能派上用场。
1.1 HTML 节点概览
HTML 节点是 n8n 的一个核心节点,它提供了处理 HTML 内容的多种功能。在 n8n 的较新版本中(0.213.0 及以后),这个节点整合并取代了旧版的 “HTML Extract” 节点。如果你使用的是更早的版本,可能会看到旧的节点,但功能核心是相似的。
这个节点主要有三大核心能力:
- 生成 HTML 模板 (Generate HTML template):允许你动态创建 HTML 内容。你可以结合固定的 HTML 标签、CSS 样式、甚至 n8n 的表达式
{{ }}来插入来自工作流其他节点的数据,生成定制化的 HTML 片段或完整文档。 - 提取 HTML 内容 (Extract HTML content):这是大家最常用的功能,也就是所谓的“网页抓取”或“网页解析”。你可以指定网页的 HTML 源码,然后通过 CSS 选择器精确地定位到你想要的数据(如文字、链接、图片地址等)并将其提取出来。
- 转换为 HTML 表格 (Convert to HTML Table):可以将来自其他节点(如数据库、Google Sheets)的结构化数据(通常是 JSON 数组)快速转换成一个 HTML 表格,方便在邮件或网页中展示。
对于零基础的读者来说,最直观的应用就是提取 HTML 内容。想象一下,你想监控某个商品的价格,或者想自动收集某个网站上的新闻标题,这个功能就能帮你实现。而生成 HTML 模板和转换为 HTML 表格则在你需要将处理后的数据以更美观、结构化的方式(如发送报告邮件)呈现时非常有用。
需要注意的是,在使用“生成 HTML 模板”功能时,如果模板中插入了来自不可信来源的数据,可能会引入跨站脚本攻击(XSS)的风险,需要特别小心。
1.2 参数配置详解
配置 HTML 节点,关键在于理解不同操作模式下的参数。
- Operation (操作):这是你首先要选择的,决定了节点要执行哪种任务:
Generate HTML template、Extract HTML content还是Convert to HTML Table。
1.2.1 操作 1: Generate HTML template (生成 HTML 模板)
当你选择这个操作时,主要配置项是一个大的文本框,用于编写你的 HTML 模板。
- Template (模板):
- 你可以在这里输入标准的 HTML 代码,例如
<h1>{{ $json.title }}</h1><p>这是报告内容...</p>。 - 可以包含 CSS 样式,需要写在
<style>标签内,例如<style> p { color: blue; } </style>。 - 可以包含 JavaScript 代码,需要写在
<script>标签内,但n8n 不会执行这些 JavaScript 代码。它们只是作为文本包含在输出的 HTML 中。 - 最强大的地方在于可以使用 n8n 表达式
{{ }}来动态插入数据。例如,{{ $json.productName }}会将上一个节点输出数据中productName字段的值插入到 HTML 中。你可以使用 n8n 提供的各种内置变量和方法。
- 你可以在这里输入标准的 HTML 代码,例如
1.2.2 操作 2: Extract HTML content (提取 HTML 内容)
这是功能最丰富也最常用的操作,参数相对复杂一些。
- Source Data (源数据):指定你的 HTML 内容来源。
- JSON: 如果你的 HTML 内容是前一个节点输出的一个 JSON 字段的值(通常是一个长字符串),选择此项。你需要指定:
- JSON Property (JSON 属性):包含 HTML 文本的那个字段的名称。例如,如果上一个 HTTP Request 节点将网页源码存储在名为
data的字段里,这里就填data。这个字段的值可以是一个字符串,或者一个包含多个 HTML 字符串的数组。翔宇提醒:这里填的是字段名,不是 HTML 内容本身,也不是 n8n 表达式。很多新手会在这里直接粘贴 HTML 代码或者写表达式{{ $json.data }},导致报错 “No property named…”。请务必只填写属性名,并确保模式是 “Fixed” 而不是 “Expression”。
- JSON Property (JSON 属性):包含 HTML 文本的那个字段的名称。例如,如果上一个 HTTP Request 节点将网页源码存储在名为
- Binary (二进制):如果你的 HTML 内容是前一个节点输出的一个二进制文件字段(比如一个
.html文件),选择此项。你需要指定:- Input Binary Field (输入二进制字段):包含 HTML 二进制数据的那个字段的名称。同样,值可以是字符串或字符串数组。
- JSON: 如果你的 HTML 内容是前一个节点输出的一个 JSON 字段的值(通常是一个长字符串),选择此项。你需要指定:
- Extraction Values (提取值):这是配置提取规则的核心区域。你可以添加一个或多个提取规则。对于每一条规则,你需要配置:
- Key (键):给你要提取的数据起个名字。这个名字将作为输出 JSON 中的字段名。例如,如果你想提取价格,可以命名为
price。 - CSS Selector (CSS 选择器):这是定位 HTML 元素的神奇语法。你需要提供一个 CSS 选择器字符串,告诉 n8n 去 HTML 的哪个位置找数据。
如何获取 CSS 选择器?对于零基础用户,最简单的方法是使用浏览器的开发者工具:- 在你想提取数据的网页元素上右键单击。选择“检查”或“Inspect Element”。浏览器会打开开发者工具,并高亮显示对应的 HTML 代码。在 HTML 代码上右键单击,通常会有关“复制”(Copy)的选项,里面会有“复制选择器”(Copy Selector)或“复制 CSS 选择器”(Copy CSS Selector)的选项。点击它!将复制到的选择器粘贴到 n8n 的这个字段里。例如,你可能会得到类似
#main-title或.product-price这样的选择器。
- 常见的简单选择器:
h1: 选取所有<h1>标题标签。p: 选取所有<p>段落标签。a: 选取所有<a>链接标签。img: 选取所有<img>图片标签。.classname: 选取所有 class 属性为classname的元素 (点号开头)。#idname: 选取 id 属性为idname的元素 (井号开头)。
- 示例:在一个博客页面,提取文章标题的选择器可能是
.post.item-title a。 - 翔宇的警告:“网站是会变的!今天能用的 CSS 选择器,明天可能因为网站结构更新就失效了。构建工作流时要有防御性思维,比如检查提取结果是否为空,如果为空则发出提醒,或者尝试备用选择器。” 这点非常重要,网页抓取天然具有脆弱性。
- 在你想提取数据的网页元素上右键单击。选择“检查”或“Inspect Element”。浏览器会打开开发者工具,并高亮显示对应的 HTML 代码。在 HTML 代码上右键单击,通常会有关“复制”(Copy)的选项,里面会有“复制选择器”(Copy Selector)或“复制 CSS 选择器”(Copy CSS Selector)的选项。点击它!将复制到的选择器粘贴到 n8n 的这个字段里。例如,你可能会得到类似
- Return Value (返回值):选择你想从找到的元素中提取什么类型的数据。
- Text (文本):获取元素内可见的文本内容。这是最常用的,用于提取信息。还有一个Skip Selectors (跳过选择器)的选项,可以让你忽略某些子元素内的文本,例如,提取段落
<p>的文本,但忽略其中<span>标签内的文字。 - HTML (HTML):获取选中元素内部的原始 HTML 代码。如果你需要元素的结构或嵌套内容,这个选项很有用。
- Attribute (属性):获取 HTML 元素的某个特定属性的值。比如链接的 URL (
href)、图片的来源 (src)、元素的class或id等。选择此项后,需要额外填写Attribute (属性)字段,指明要哪个属性的值,例如填href或src。 - Value (值):专门用于表单元素,如
<input>,<select>,<textarea>,获取它们当前的值。
- Text (文本):获取元素内可见的文本内容。这是最常用的,用于提取信息。还有一个Skip Selectors (跳过选择器)的选项,可以让你忽略某些子元素内的文本,例如,提取段落
- Return Array (返回数组):这是一个开关。如果你的 CSS 选择器找到了多个匹配的元素(例如,页面上所有的商品价格),打开这个开关 (ON),提取到的所有值会以一个列表(数组)的形式返回。如果关闭 (OFF),通常只会返回第一个找到的值,或者一个合并后的字符串(具体行为可能略有差异,以实际测试为准)。
- Key (键):给你要提取的数据起个名字。这个名字将作为输出 JSON 中的字段名。例如,如果你想提取价格,可以命名为
- Extract HTML Content options (提取 HTML 内容选项):这些是微调提取过程的附加设置。
- Trim Values (修剪值):打开后,移除提取到的值开头和结尾的所有空格和换行符。通常很有用,可以让数据更干净。
- Clean Up Text (清理文本):打开后,进行更彻底的清理,除了移除开头结尾的空白,还会移除文本中间多余的空格和换行符,将连续的多个空白压缩成一个空格。
如何选择 Trim Values 和 Clean Up Text?这取决于你想要的输出格式。如果文本内部的空格和换行符对你很重要(比如代码片段或预格式化文本),只使用 Trim Values 可能更安全。如果只想要纯粹的、易于阅读的文本块,Clean Up Text 通常效果更好。但要注意,Clean Up Text 可能会改变原始文本的格式,有时可能清理过度。
1.2.3 操作 3: Convert to HTML Table (转换为 HTML 表格)
这个操作相对简单,主要用于将结构化数据转换成 HTML 表格。
- Input Data (输入数据):它期望接收来自上一个节点的、包含多个 JSON 对象的一个数组。数组中的每个 JSON 对象会被转换成表格的一行,对象的键(key)会成为表头(header)。
- Options (选项):提供了一些基本的样式控制。
- Capitalize Headers (大写表头):是否自动将表头文字转换为大写。
- Custom Styling (自定义样式):是否启用自定义样式。启用后,下方会出现更多属性设置。
- Caption (表格标题):为表格添加一个标题 (
<caption>标签)。 - Table Attributes (表格属性):给
<table>标签添加 HTML 属性,最常用的是style属性来定义边框、宽度等,例如style="border: 1px solid black; width: 100%;"。 - Header Attributes (表头属性):给表头的单元格
<th>添加属性,如style="background-color: #f2f2f2;"。 - Row Attributes (行属性):给表格的每一行
<tr>添加属性。 - Cell Attributes (单元格属性):给表格的普通单元格
<td>添加属性。
- 翔宇的建议:“‘转换为 HTML 表格’ 功能对于快速生成报告非常方便。但如果表格是要嵌入到邮件里的,建议样式尽量从简,避免使用过于复杂的 CSS,以保证在各种邮件客户端的兼容性。”
1.3 数据映射与流转
理解数据如何在 HTML 节点中流入和流出至关重要。
- 输入 (Input):
- Generate Template (生成模板):接收标准的 n8n 数据项(一个包含 JSON 对象的数组)。节点通过模板中的表达式
{{ }}从这些输入项的json对象中提取数据,并将其嵌入到 HTML 模板中。 - Extract Content (提取内容):期望接收一个(或多个)n8n 数据项,其中每个项的
json对象里包含一个特定字段,该字段的值是 HTML 源码字符串或二进制数据。数据结构通常是[{ "json": { "propertyName": "<html>...</html>" } }]或[{ "json": { "binaryPropertyName": {...binary data... } } }]。propertyName或binaryPropertyName就是你在 “Source Data” 中指定的字段名。 - Convert to Table (转换表格):期望接收一个包含多个 JSON 对象的数组。数组中的每个对象代表表格的一行。例如:“。
- Generate Template (生成模板):接收标准的 n8n 数据项(一个包含 JSON 对象的数组)。节点通过模板中的表达式
- 输出 (Output):
- Generate Template (生成模板):输出的数据项中,会包含一个新字段(通常默认名为
html,但取决于节点实现或可配置),其值为生成的 HTML 字符串。 - Extract Content (提取内容):输出的数据项中,会包含你在 “Extraction Values” 中定义的各个 “Key” 作为字段名,对应的值就是提取到的数据。如果某个 Key 设置了 “Return Array” 为 ON 并且找到了多个结果,那么对应的值就是一个数组。例如:
} }]。 - Convert to Table (转换表格):通常输出一个数据项,其中包含一个字段(例如
html),其值为生成的整个 HTML 表格字符串。
- Generate Template (生成模板):输出的数据项中,会包含一个新字段(通常默认名为
- 链接数据 (Expressions):再次强调,表达式
{{ }}是数据映射的关键。- 在 “Generate HTML Template” 中,表达式用于将输入数据注入模板。
- 在 “Extract HTML Content” 的 “Source Data” 配置中,你不使用表达式,而是直接填写包含 HTML 的字段名。
- 在 “Convert to HTML Table” 中,节点会自动处理输入数组,你通常不需要在节点内部配置复杂的表达式,但可能需要确保上游节点输出的数据格式正确。
1.4 工作流实战:HTML 节点应用场景
理论讲完了,让我们看看 HTML 节点在实际工作流中能做些什么。
场景 1: 简单的网页抓取(商品价格监控) 目标: 从一个电商网站的产品页面提取当前价格。
- 步骤:
- HTTP Request 节点:
- Method:
GET - URL: 输入目标商品的页面网址。
- Options -> Response Format: 选择
String(或Text),确保获取到的是原始 HTML 文本,而不是 n8n 尝试解析的 JSON。 - (可选但推荐) Options -> Headers: 添加一个
User-Agent头,模拟浏览器访问,减少被网站屏蔽的概率。例如:User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36。
- Method:
- HTML 节点:
- Operation:
Extract HTML content。 - Source Data -> JSON Property: 填写 HTTP Request 节点输出 HTML 的字段名(通常是
data)。 - Extraction Values:
- Add Value:
- Key:
price - CSS Selector: 使用浏览器开发者工具找到价格元素的 CSS 选择器,例如
.price-tag或#product-price,粘贴到这里。 - Return Value:
Text。
- Key:
- Add Value:
- Operation:
- HTTP Request 节点:
- 翔宇的经验: “刚开始练习抓取时,先找那些结构简单、内容是静态加载的网站(即打开网页源码就能看到所有内容的)。那些需要大量 JavaScript 交互才能显示内容的网站,用这个基础的 HTML 节点可能抓不到,需要更高级的技术或服务。”
场景 2: 生成简单的 HTML 报告并通过邮件发送 目标: 从 Google Sheets 读取数据,将其格式化为 HTML 表格,然后嵌入邮件发送。 - 步骤:
- Google Sheets 节点: 读取需要的表格数据。输出应该是一个包含多行数据的数组。
- HTML 节点:
- Operation:
Convert to HTML Table。 - (节点会自动接收 Google Sheets 的输出数组)。
- 根据需要配置 Options 中的样式。
- Operation:
- Send Email 节点 (或 Gmail 等):
- 在邮件正文 (Body) 类型选择 HTML。
- 在 HTML 正文编辑器中,使用表达式
{{ $('HTML').item.json.html }}(假设 HTML 节点名为 ‘HTML’ 且输出字段为 ‘html’)来插入生成的表格。
- 翔宇的经验: “如果报告不只需要一个表格,还想加点文字说明怎么办?可以在‘Convert to HTML Table’节点之后再加一个 HTML 节点,选择‘Generate HTML Template’操作。在这个模板里,你可以写上说明文字,然后用表达式把前面生成的表格 HTML (
{{ $('HTML').item.json.html }}) 插到合适的位置,生成一个更完整的报告 HTML。”
场景 3: 从页面提取所有链接 目标: 获取某个博客首页上所有文章的链接。 - 步骤:
- HTTP Request 节点:
- Method:
GET - URL: 博客首页地址。
- Response Format:
String。
- Method:
- HTML 节点:
- Operation:
Extract HTML content。 - Source Data -> JSON Property:
data。 - Extraction Values:
- Add Value:
- Key:
links - CSS Selector: 找到包含文章链接的
<a>标签的选择器,例如article h2 a(选取article元素内h2标题下的a链接)。 - Return Value:
Attribute。 - Attribute:
href(因为我们要链接的 URL)。 - Return Array:务必打开 (ON)。
- Key:
- Add Value:
- Operation:
- HTTP Request 节点:
- 翔宇的经验: “提取多个结果时,千万别忘了打开‘Return Array’开关!否则你辛辛苦苦配好选择器,结果却只拿到第一个链接,那就白费功夫了。”
- 参考官方模板: n8n 官方提供了很多包含 HTML 节点的工作流模板,例如网页抓取与 AI 总结、自动化网页抓取并存入表格等。这些都是非常好的学习和借鉴资源。
1.5 常见报错与解决方案
使用 HTML 节点时,遇到报错是很常见的,尤其是对于初学者。下面是一些典型问题及其排查思路:
报错: “No property named ‘…’ exists” (提取内容时) 原因 1: 在 “Source Data” 的 “JSON Property” 中填写的字段名不正确,或者模式设置成了 “Expression” 而非 “Fixed”。
- 解决: 仔细检查上一个节点的输出,确保填写的字段名与实际包含 HTML 的字段名完全一致(大小写敏感)。确认该参数的模式是 “Fixed”。
- 原因 2: HTML 内容嵌套在 JSON 结构中比较深的层级,节点可能处理不好。
- 解决: 在 HTML 节点之前加一个 Set 节点,使用 “Move Value” 模式,将深层嵌套的 HTML 字段(如
body.html)移动到一个顶层的新字段(如htmlData)。然后在 HTML 节点中引用这个新字段htmlData。
- 解决: 在 HTML 节点之前加一个 Set 节点,使用 “Move Value” 模式,将深层嵌套的 HTML 字段(如
- 原因 3: 工作流处理多个输入项,但其中某些项缺少指定的 HTML 字段。
- 解决: 在 HTML 节点前使用If 节点或 Filter 节点,过滤掉缺少 HTML 字段的数据项。或者,在 HTML 节点的 “Settings” 中谨慎使用 “Always Output Data” 选项(但这可能输出空结果)。
报错: 提取结果为空或没有数据 原因 1:CSS 选择器不正确或已失效。 - 解决: 返回浏览器开发者工具,重新检查并复制选择器。确保选择器足够精确,能够唯一定位到目标元素。注意网站可能已经改版,导致旧的选择器失效。
- 解决: 在 HTML 节点前使用If 节点或 Filter 节点,过滤掉缺少 HTML 字段的数据项。或者,在 HTML 节点的 “Settings” 中谨慎使用 “Always Output Data” 选项(但这可能输出空结果)。
- 原因 2:Return Value选择错误。
- 解决: 如果想提取链接地址 (
href) 或图片地址 (src),必须选择Attribute并指定属性名href或src,而不是选择Text。
- 解决: 如果想提取链接地址 (
- 原因 3: 想要的数据是通过 JavaScript 动态加载的,在 n8n 获取到的初始 HTML 源码中并不存在。
- 解决: 这种情况比较复杂,基础的 HTML 节点无能为力。翔宇的建议:“这通常需要用到能模拟浏览器行为的工具(比如 Puppeteer 或 Playwright,但这需要写代码),或者使用专门的第三方网页抓取服务(如 ScrapingBee,n8n 模板中也有用到)。”
- 原因 4: 源 HTML 结构本身无效,导致解析失败(例如,表格单元格
<td>出现在<table>标签之外)。- 解决: 如果可能,尝试在上游修复 HTML 结构。例如,使用 Set 节点将零散的
<td>包裹在<table><tr>...</tr></table>结构中。
报错: “Converting circular structure to JSON” / “extractionValues.values is not iterable” 原因: 通常与传入了复杂或不规范的数据结构有关,特别是嵌套的 HTML 处理不当时容易触发。可能是节点试图处理一个无法序列化的对象。
- 解决: 如果可能,尝试在上游修复 HTML 结构。例如,使用 Set 节点将零散的
- 解决: 尝试简化输入数据。使用前面提到的 Set 节点将 HTML 移到顶层字段通常能解决这类问题。确保传入 HTML 节点的 JSON 属性值是一个简单的字符串或字符串数组。
报错: HTML 节点之前的 HTTP Request 节点失败 (如 403 Forbidden, 302 Redirect, Timeout) 原因: 目标网站有反爬机制、需要登录、发生了页面跳转、或者服务器响应慢。 - 解决: 配置 HTTP Request 节点:
- 添加
User-Agent请求头模拟浏览器。 - 在 Options 中开启
Follow Redirects处理跳转。 - 在 Options 中增加
Timeout时间(单位毫秒)。 - 如果需要登录,配置相应的认证方式 (Credentials)。
- 在 Settings 中开启
Retry On Fail进行重试,或开启Continue On Fail并结合 If 节点检查后续的状态码来处理错误。
- 添加
- 翔宇的调试技巧: “一定要善用节点下方的 ‘Test step’ (或 ‘Execute Node’) 按钮!一步一步执行,检查每个节点的输出。如果 HTML 节点报错或结果不对,首先要看它上一个节点(比如 HTTP Request)的输出,确认 HTML 数据是否真的被正确获取了,内容是不是你预期的。”
1.6 注意事项与最佳实践
用好 HTML 节点,还需要注意以下几点:
- 尊重网站规则 (robots.txt):在抓取网站前,检查网站根目录下的
robots.txt文件,了解网站所有者允许或禁止爬虫访问哪些路径。不要过于频繁地请求,给对方服务器造成负担。翔宇的观点:“自动化应负责任。优先查找网站是否提供官方 API,使用 API 总是比网页抓取更稳定、更合法。” - 应对网站变化:网页结构随时可能改变,导致你的 CSS 选择器失效。翔宇的建议:“在工作流中加入检查机制。例如,如果 HTML 节点提取结果为空,可以通过 If 节点判断,然后发送通知给自己,提醒检查和修复选择器。”
- 理解动态内容 (JavaScript):要清楚 HTML 节点主要处理的是服务器返回的初始 HTML 源码。如果很多内容是靠浏览器执行 JavaScript 后才加载显示的,这个节点可能看不到。翔宇的提醒:“如果你需要的数据在页面加载完成后才出现,就需要考虑其他方案了。”
- HTML 的有效性:节点处理格式良好、结构规范的 HTML 时效果最好。遇到不规范或残缺的 HTML,解析可能会出错或产生意想不到的结果。
- 生成内容保持简洁:尤其是在生成用于邮件的 HTML 时,避免复杂的布局和样式,优先保证兼容性。
- 安全意识 (XSS):在生成 HTML 时,如果模板中嵌入了外部(尤其是用户输入的)数据,要警惕跨站脚本攻击(XSS)风险。对不可信数据进行适当的清理或转义。
- 选择器要精确:避免使用过于宽泛的选择器(如
div,span),它们可能匹配到页面上成百上千个元素,导致性能问题或提取到错误数据。尽量使用 ID、唯一的 Class 组合,或者更具体的路径来定位。 - 充分测试:用不同的页面、不同类型的内容来测试你的提取规则,确保其鲁棒性。
掌握了 HTML 节点,你就拥有了与 Web 世界直接对话的能力。接下来,我们看看如何处理另一种常见的文本格式——Markdown。
第二部分:Markdown 节点深度解析
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成结构化的 HTML。它诞生之初就是为了让网络写作更简单、更专注内容本身。如今,从 GitHub 的 README 文件、技术文档,到笔记应用、论坛发帖,Markdown 无处不在。n8n 的 Markdown 节点,就是帮助我们在这种简洁的文本格式和通用的 HTML 格式之间自由转换的桥梁。
2.1 Markdown 节点概览
Markdown 节点是 n8n 的一个核心转换节点,功能非常专一:在 Markdown 和 HTML 之间进行相互转换。
它是什么?一个用于格式转换的工具节点。
Markdown 是什么?(简述)一种用简单符号(如 # 表示标题, * 或 - 表示列表项, 文字 表示加粗)来标记文本格式的语法。写起来像普通文本,但可以被程序识别并转换成对应的 HTML 标签。例如,输入 # 一级标题 会被转换成 <h1>一级标题</h1>,输入 * 列表项 会被转换成 <li>列表项</li>。
- 核心能力: 提供两种转换模式:
- Markdown to HTML (Markdown 转 HTML):将输入的 Markdown 文本转换成 HTML 代码。
- HTML to Markdown (HTML 转 Markdown):将输入的 HTML 代码转换回 Markdown 文本。
为什么零基础用户需要它? 场景一:用户通过 n8n 的表单提交了一段包含简单格式(如列表、加粗)的反馈意见(用 Markdown 写的),你想把这段反馈以格式化的形式发送到 HTML 邮件里,就需要 Markdown 转 HTML。
- 场景二:你从某个地方获取了一段简单的 HTML 内容(比如一个网页的部分内容),想把它存成纯文本的 Markdown 笔记,就需要 HTML 转 Markdown。
这个节点本身不涉及复杂的逻辑,主要是理解 Markdown 语法和节点提供的各种转换选项。
2.2 参数配置详解
配置 Markdown 节点相对直观,主要围绕模式选择、输入输出和转换选项。
- Mode (模式):首先选择转换方向,是
Markdown to HTML还是HTML to Markdown。 - HTML or Markdown (HTML 或 Markdown 输入字段):
- 这是一个文本输入区域,标签会根据你选择的
Mode动态变化。如果选择Markdown to HTML,它就叫Markdown;如果选择HTML to Markdown,它就叫HTML。 - 你可以在这里直接输入或粘贴文本内容。
- 更常用的是,使用 n8n 表达式
{{ }}从上一个节点获取文本数据。例如,如果上一个节点输出的 JSON 中有一个名为notes的字段包含 Markdown 文本,你可以在这里填入{{ $json.notes }}。
- 这是一个文本输入区域,标签会根据你选择的
- Destination Key (目标键):
- 指定转换后的结果要存储在 n8n 数据项的哪个字段名下。例如,你可以填
convertedHtml或markdownOutput。 - 同样支持使用点
.来指定嵌套字段,如output.formattedText。
- 指定转换后的结果要存储在 n8n 数据项的哪个字段名下。例如,你可以填
- Node Options (节点选项):这部分是 Markdown 节点,特别是
Markdown to HTML模式下,配置最丰富的地方。它提供了大量选项来控制转换的行为和兼容性。- 重要提示 (关于无表格约束):官方文档通常使用表格来展示这些选项。根据本次教程的要求,我们将不使用 Markdown 表格,而是通过结构化的列表和文字描述来详细介绍每一个选项。
- Markdown to HTML Options (Markdown 转 HTML 选项):以下是该模式下的主要选项,解释了它们的作用和默认值。请注意,选项非常多,反映了 Markdown 存在多种“方言”和扩展。
Add Blank To Links (给链接添加 Blank) 描述:是否让转换后的 HTML 链接在新窗口或新标签页打开(通过添加target="_blank"属性)。- 默认值:Disabled (禁用)。
Automatic Linking To URLs (自动链接 URL) 描述:是否自动将文本中看起来像 URL 的字符串(如https://example.com)转换成可点击的 HTML 链接 (<a>标签)。 - 默认值:Disabled (禁用)。
Backslash Escapes HTML Tags (反斜杠转义 HTML 标签) 描述:是否允许使用反斜杠\来转义 HTML 的尖括号<和>,使其显示为字符本身而不是被当作 HTML 标签解析。例如,启用后,\<div\>会输出<div>。 - 默认值:Disabled (禁用)。
Complete HTML Document (完整 HTML 文档) 描述:输出是包含<html>,<head>,<body>等标签的完整 HTML 文档,还是仅仅输出转换后的 HTML 片段。 - 默认值:Disabled (禁用,只输出片段)。
Customized Header ID (自定义标题 ID) 描述:是否支持在 Markdown 标题后面用{ #custom-id }的语法来指定生成的 HTML 标题标签(如<h1>)的id属性。 - 默认值:Disabled (禁用)。
Emoji Support (Emoji 支持) 描述:是否将文本表示的 Emoji(如:),:(,:heart:等,具体支持哪些取决于底层库 Showdown)转换成实际的 Emoji 字符。 - 默认值:Disabled (禁用)。
Encode Emails (编码邮箱地址) 描述:是否将 ASCII 字符组成的邮箱地址转换成对应的十进制实体编码,这是一种简单的反爬虫、反垃圾邮件的混淆手段。 - 默认值:Enabled (启用)。
Exclude Trailing Punctuation From URLs (从 URL 中排除结尾标点) 描述:当启用了 “Automatic Linking To URLs” 时,这个选项决定是否将紧跟在 URL 后面的标点符号(如逗号、句号)排除在链接之外。 - 默认值:Disabled (禁用)。
GitHub Code Blocks (GitHub 代码块) 描述:是否支持 GitHub Flavored Markdown (GFM) 风格的代码块语法,即使用三个反引号并指定语言(如python)。 - 默认值:Enabled (启用)。
GitHub Compatible Header IDs (GitHub 兼容标题 ID) 描述:生成的 HTML 标题id是否遵循 GitHub 的规则(小写字母,用连字符-替换空格,移除特殊字符)。 - 默认值:Disabled (禁用)。
GitHub Mention Link (GitHub 提及链接) 描述:当启用 “GitHub Mentions” 时,可以修改@username转换成的链接的基础 URL(默认为https://github.com/username)。 - 默认值:Disabled (禁用,使用默认 GitHub 链接)。
GitHub Mentions (GitHub 提及) 描述:是否支持将@username这样的文本转换成指向对应 GitHub 用户主页的链接。 - 默认值:Disabled (禁用)。
GitHub Task Lists (GitHub 任务列表) 描述:是否支持 GFM 的任务列表语法,即- [ ] 未完成和- [x] 已完成。 - 默认值:Disabled (禁用)。
Header Level Start (标题起始级别) 描述:设置 Markdown 的#对应于 HTML 的哪个级别的标题。例如,设为 2,则#对应<h2>,##对应<h3>,以此类推。 - 默认值:1 (
#对应<h1>)。
Mandatory Space Before Header (标题前强制空格) 描述:是否要求#和标题文本之间必须有一个空格才被识别为标题。启用后,##MyHeader会被视为普通文本。 - 默认值:Disabled (禁用)。
Middle Word Asterisks (词中星号) 描述:决定如何处理出现在单词中间的星号*。禁用时,可能被解析为强调标记(取决于具体上下文和数量);启用时,强制将其视为普通的星号字符。 - 默认值:Disabled (禁用)。
Middle Word Underscores (词中下划线) 描述:决定如何处理出现在单词中间的下划线_。禁用时,可能被解析为强调标记;启用时,强制将其视为普通的下划线字符。 - 默认值:Disabled (禁用)。
No Header ID (无标题 ID) 描述:是否完全禁止为生成的 HTML 标题自动添加id属性。 - 默认值:Disabled (禁用,即默认会尝试生成 ID)。
Parse Image Dimensions (解析图片尺寸) 描述:是否支持在 Markdown 图片语法中添加=WidthxHeight来指定图片的width和height属性,例如。 - 默认值:Disabled (禁用)。
Require Space Before Heading Text (标题文本前需要空格) (注意:这个选项描述与 “Mandatory Space Before Header” 非常相似,可能是文档重复或历史遗留。在实际使用中,请以节点界面为准,它们可能控制同一行为。) - 默认值:(参考 Mandatory Space Before Header) Disabled。
Simple Line Breaks (简单换行) 描述:是否将 Markdown 中的单个换行符处理为 HTML 中的<br>标签。标准的 Markdown 需要两个或更多连续换行才产生新的段落<p>。启用这个选项会让换行行为更像普通文本编辑器。 - 默认值:Disabled (禁用)。
Smart Indentation (智能缩进) (注意:文档未提供此选项的详细描述。可能与列表或代码块的缩进处理有关。建议在 n8n 界面查看提示或进行测试。) - 默认值:(未知)。
Smooth Live Preview (平滑实时预览) (注意:文档未提供此选项的详细描述。这听起来更像是编辑器界面的特性,可能对节点的核心转换逻辑影响不大。建议在 n8n 界面查看提示或进行测试。) - 默认值:(未知)。
Split Adjacent Block Quotes (分割相邻块引用) 描述:是否将仅由一个空行分隔的两个块引用(以>开头)视为两个独立的<blockquote> 元素。禁用时,它们会被合并成一个。 - 默认值:Disabled (禁用)。
Strikethrough (删除线) 描述:是否支持使用两个波浪线~~包裹文本来实现删除线效果 (转换成<del>或<s>标签)。 - 默认值:Disabled (禁用)。
Tables Header ID (表格标题 ID) 描述:是否为生成的 HTML 表格的表头单元格<th>自动添加id属性。 - 默认值:Disabled (禁用)。
Tables Support (表格支持) 描述:是否支持 Markdown 的表格语法(使用|和-来绘制表格)。 - 默认值:Disabled (禁用)。
Underline (下划线) (注意:文档未提供此选项的详细描述。标准的 Markdown 没有下划线语法,这可能是某个扩展语法。建议在 n8n 界面查看提示或进行测试。) - 默认值:(未知)。
为什么有这么多选项?Markdown 本身非常简洁,但这也导致了许多平台(如 GitHub)在此基础上添加了自家的扩展功能(任务列表、表格、改进的代码块等)。n8n 的 Markdown 节点试图通过这些选项来兼容不同的 Markdown “方言”和满足多样化的 HTML 输出需求。对于初学者来说,这意味着可能需要根据 Markdown 源文本的风格(特别是是否使用了 GitHub Flavored Markdown 的特性)来启用相应的选项,才能得到预期的 HTML 结果。翔宇的建议:“从默认设置开始。只有当你的输入 Markdown 明确使用了表格、任务列表等扩展语法时,才需要去开启对应的支持选项。不要一次性打开所有选项。”
- 默认值:Disabled (禁用)。
- HTML to Markdown Options (HTML 转 Markdown 选项):
- 注意:文档对这部分选项的描述非常有限。节点主要依赖底层的
node-html-markdown库进行转换,其默认行为可能已经能处理常见的 HTML 标签,如<h1>-<h6>, <p>, <a>, <img>, <ul>, <ol>。 - 通常这类转换器的选项可能涉及如何处理未知的 HTML 标签、是否保留某些属性、或者对特定标签(如表格)的转换策略。由于缺乏具体文档,建议用户在需要进行 HTML 到 Markdown 转换时,先用简单的 HTML 测试默认效果,如果效果不理想,再查看节点界面是否有可调整的选项。
- 底层解析器 (Underlying Parsers):
- Markdown to HTML: 使用(https://github.com/showdownjs/showdown) 库。这是一个成熟的 JavaScript Markdown 转换器,支持核心 Markdown 语法和许多扩展(通过选项启用)。
- HTML to Markdown: 使用 node-html-markdown 库。这是一个用于将 HTML 转换回 Markdown 的 Node.js 库。
- 了解这些只是背景知识,用户通常不需要直接与这些库交互,但它解释了节点功能和选项的来源。
- 翔宇的建议:“转换效果一定要测试!特别是 Markdown 转 HTML,生成的 HTML 在不同的地方(浏览器、邮件客户端)渲染效果可能不同。务必预览一下,确保格式符合预期。某些选项组合可能会产生细微但重要的视觉差异。”也提到了测试选项的建议。
- 注意:文档对这部分选项的描述非常有限。节点主要依赖底层的
2.3 数据映射与流转
Markdown 节点的数据流相对简单:
- 输入 (Input):
- 期望接收一个 n8n 数据项,其
json对象中包含待转换的 Markdown 或 HTML 文本。 - 通常这个文本数据是通过表达式
{{ }}映射到节点的 “HTML or Markdown” 输入字段的。例如,“。
- 期望接收一个 n8n 数据项,其
- 输出 (Output):
- 产生一个 n8n 数据项,其中包含一个由 “Destination Key” 参数指定的新字段,该字段的值是转换后的文本(HTML 或 Markdown)。
- 例如,如果输入是上面的 Markdown,模式是
Markdown to HTML,目标键是htmlOutput,则输出可能是 “ (假设保留了原始输入字段)。
- 数据流位置:
- 通常位于提供了原始文本的节点(如 Read File, HTTP Request, Form Trigger, Set 节点)之后。
- 它的下游节点则会消费转换后的格式(如 Send Email 消费 HTML,Write File 或 Notion 节点可能消费 Markdown)。
2.4 工作流实战:Markdown 节点应用场景
让我们看看 Markdown 节点在实际工作流中的应用实例。
场景 1: 格式化用户通过表单提交的文本,用于 HTML 邮件 目标: 用户在 n8n Form Trigger 提供的表单的文本域中,可以使用 Markdown 语法(如写列表、加粗)来提交反馈。工作流需要将这些反馈格式化后,通过 HTML 邮件发送给管理员。
- 步骤:
- n8n Form Trigger 节点: 配置一个表单,包含一个 Textarea (多行文本) 字段,用于接收用户的 Markdown 输入(例如字段名为
feedbackText)。 - Markdown 节点:
- Mode:
Markdown to HTML。 - Markdown Input: 使用表达式
{{ $json.feedbackText }}获取表单提交的文本。 - Destination Key:
formattedFeedback。 - Options: 根据需要启用,例如
GitHub Task Lists(如果允许用户提交任务列表),Tables Support(如果允许提交表格),Simple Line Breaks(如果希望用户的单次回车也换行)。
- Mode:
- Send Email 节点:
- 邮件正文类型选择 HTML。
- 在 HTML 正文中,使用表达式
{{ $('Markdown').item.json.formattedFeedback }}(假设 Markdown 节点名为 ‘Markdown’) 插入转换后的 HTML。
- n8n Form Trigger 节点: 配置一个表单,包含一个 Textarea (多行文本) 字段,用于接收用户的 Markdown 输入(例如字段名为
- 翔宇的价值: “这样做可以让用户轻松地为他们的输入添加格式,比如项目符号列表、粗体强调、甚至代码片段,使得沟通内容更清晰、更丰富,而你只需要一个 Markdown 节点就能搞定格式转换。”
场景 2: 将 Notion 页面的部分内容转换为 Markdown 存储 目标: 从一个 Notion 页面抓取主要内容(通常是富文本,接近 HTML),并将其保存为 Markdown 文件,方便版本控制或在其他地方使用。 - 步骤:
- Notion 节点: 使用 “Page” 资源的 “Get Blocks” 操作获取页面内容块。Notion 的块数据是一种特殊的 JSON 结构。
2.(关键步骤)处理 Notion Block 数据:- 选项 A (社区节点): 使用社区开发的
n8n-nodes-notion-markdown节点。这个节点专门设计用于在 Notion Block JSON 和 Markdown 之间进行双向转换。配置其 Operation 为Notion to Markdown,Input Notion Blocks 为上一步 Notion 节点的输出。 - 选项 B (手动处理 – 较复杂): 如果不用社区节点,可能需要一个Code 节点来遍历 Notion Block JSON,根据不同的 block 类型 (paragraph, heading, list item 等) 手动将其转换成近似的 HTML 字符串。这需要一定的 JavaScript 知识。
- 选项 A (社区节点): 使用社区开发的
- Markdown 节点:
- Mode:
HTML to Markdown。 - HTML Input: 输入上一步骤处理得到的 HTML 或 Markdown 字符串 (如果使用社区节点且其直接输出 Markdown,则此步可省略或用于进一步清理)。
- Destination Key:
markdownContent。
- Mode:
- Write File 节点: 将
markdownContent字段的内容写入到一个.md文件中。
- Notion 节点: 使用 “Page” 资源的 “Get Blocks” 操作获取页面内容块。Notion 的块数据是一种特殊的 JSON 结构。
- 翔宇的说明: “直接用核心 Markdown 节点处理 Notion 内容比较困难,因为 Notion 的数据结构不是标准的 HTML。强烈推荐使用像
n8n-nodes-notion-markdown这样的社区节点,它能更好地理解 Notion 的格式并进行转换。核心 Markdown 节点的 HTML 转 Markdown 功能更适合处理标准的、简单的 HTML 输入。”
场景 3: 清理和规范化大语言模型 (LLM) 的输出 目标: 调用 OpenAI 或其他 LLM 获取一段文本回复,该回复可能包含 Markdown 格式,需要将其转换为干净的 HTML 或纯文本用于后续处理。 - 步骤:
- OpenAI 节点 (或其他 LLM 节点): 获取模型的文本响应,可能存储在
response字段中。 - (可选) Set 或 Code 节点: 检查并移除 LLM 输出中可能存在的前后包裹符,如 … 或 “Here’s the response in Markdown:” 等前缀。可以使用字符串替换函数(如
.replace())来清理。- 示例 (Set 节点表达式):
{{ $json.response.replace(/^```(?:json|markdown)?\n?/, "").replace(/\n?```$/, "").replace(/^(Here is the JSON:|Here is your Markdown document:)\s*/, "") }}。
- 示例 (Set 节点表达式):
- Markdown 节点:
- Mode:
Markdown to HTML。 - Markdown Input:
{{ $json.cleanedResponse }}(假设上一步 Set 节点输出到cleanedResponse)。 - Destination Key:
htmlOutput。 - Options: 可能需要禁用
Complete HTML Document以获取 HTML 片段。
- Mode:
- (后续处理): 使用
htmlOutput进行下一步操作,或者如果需要纯文本,可以再接一个 HTML 节点 (Extract Content, Selectorbody, Return ValueText) 来剥离所有 HTML 标签。
- OpenAI 节点 (或其他 LLM 节点): 获取模型的文本响应,可能存储在
- 翔宇的技巧: “LLM 的输出格式有时不太稳定。在将其送入 Markdown 节点之前,最好先做一步清理,把那些多余的解释性文字或者代码块标记去掉,这样能提高 Markdown 节点转换的成功率和准确性。”### 2.5 常见报错与解决方案
使用 Markdown 节点通常比较顺利,但也可能遇到一些问题:
报错: 输出的 HTML 格式不符合预期 / 标签错误 原因: 选择的 “Markdown to HTML Options” 不正确,或者默认选项与输入的 Markdown 语法风格不匹配。例如,Markdown 中写了表格,但没有启用 “Tables Support” 选项;或者希望单次回车就换行,但没有启用 “Simple Line Breaks”。
- 解决: 仔细检查并调整 “Markdown to HTML Options”。确保启用的选项与你输入的 Markdown 语法一致。多尝试不同的选项组合,并实时查看输出结果进行验证。
报错: HTML 转换为 Markdown 的效果很差 原因: 输入的 HTML 过于复杂,包含大量 CSS 样式、JavaScript 或非标准的 HTML 标签。底层的node-html-markdown库可能无法完美处理所有情况。 - 解决: 尽量简化输入的 HTML 源码。接受复杂布局和样式很难精确转换回简单的 Markdown 这个事实。如果遇到特定标签转换问题,可以查阅
node-html-markdown库的文档或 issue 看看是否有已知的限制或解决方案。
报错: 节点执行失败,提示输入不是文本 原因: 错误地将一个 JSON 对象、数组或二进制数据直接映射到了 “HTML or Markdown” 输入字段,而不是其中的文本内容。 - 解决: 确保映射到输入字段的表达式最终解析为一个字符串。例如,应该使用
{{ $json.textField }}而不是{{ $json }}或{{ $input.item }}。
2.6 注意事项与最佳实践
为了更高效地使用 Markdown 节点,请记住以下几点:
- 了解你的 Markdown “方言”: 确认你处理的 Markdown 文本遵循哪种规范(是基础语法,还是 GitHub Flavored Markdown 等),然后启用对应的转换选项。
- 测试转换结果: 务必在目标环境中(如浏览器、邮件客户端)检查转换后的输出,尤其是 Markdown 转 HTML,确保渲染效果符合预期。
- 注意选项间的交互: 某些选项可能会相互影响(例如,多个与标题 ID 相关的选项)。测试组合效果。
- HTML 的复杂度: HTML 转 Markdown 最适合处理结构清晰、语义化的 HTML。复杂的 CSS 布局和脚本基本无法转换。
- 明确使用场景: 这个节点是用来转换内容格式的,不是用来复制复杂网页布局的。
- 与其他节点结合: 善用 Set 或 Code 节点进行预处理(如清理 LLM 输出)或后处理(如进一步操作转换结果)。
Markdown 节点是处理纯文本格式化的好帮手。最后,我们来攻克 XML 节点,它是处理另一种重要数据格式的关键。
第三部分:XML 节点深度解析
XML (eXtensible Markup Language) 即可扩展标记语言,它曾经是网络数据交换的通用语言,尤其是在企业级应用和 Web 服务(特别是 SOAP API)中。虽然现在 JSON 更为流行,但 XML 仍然在许多场景下被广泛使用,例如 RSS 订阅源、配置文件、以及与一些旧系统或特定行业标准的数据接口交互。n8n 的 XML 节点,就是我们用来解析(读取)和构建(生成)这种结构化数据的工具。
3.1 XML 节点概览
XML 节点是 n8n 中用于处理 XML 数据的核心节点。
它是什么?一个在 n8n 内部常用的 JSON 格式与外部系统可能使用的 XML 格式之间进行双向转换的工具。
XML 是什么?(简述)一种用标签来定义数据结构和内容的标记语言。它和 HTML 很像,都有标签(如 <tag>content</tag>),但 XML 的标签是自定义的,并且规则更严格(例如,所有标签必须闭合)。它的主要目的是传输和存储数据,而不是像 HTML 那样侧重于显示数据。一个简单的例子:<order><id>123</id><product>N8N Mug</product><quantity>2</quantity></order>。
- 核心能力: 提供两种转换模式:
- JSON to XML (JSON 转 XML):将 n8n 工作流中的 JSON 数据转换成 XML 格式的字符串。
- XML to JSON (XML 转 JSON):将输入的 XML 格式的字符串解析成 n8n 更容易处理的 JSON 对象。
为什么零基础用户需要它? 当你需要调用的 API 只接受 XML 格式的请求体时(例如一些 SOAP 服务或旧的 B2B 接口)。
- 当你调用的 API 返回的是 XML 格式的数据(例如 RSS feed 或某些银行、政府机构的接口),你需要将其转换成 JSON 才能在 n8n 中方便地提取和使用数据。
- 处理从某些系统导出的 XML 配置文件或数据文件。
理解 XML 节点,关键在于掌握 JSON 和 XML 这两种结构之间的映射关系,以及节点提供的各种选项如何影响这种映射。
3.2 参数配置详解
配置 XML 节点需要关注模式选择、输入属性名以及一系列影响转换细节的选项。
- Mode (模式):首先确定转换方向:
JSON to XML还是XML to JSON。 - Property Name (属性名称):
- 极其重要: 这个参数要求你填写包含待转换数据的那个 JSON 属性的名称。
- 对于
JSON to XML:这里填写包含要转换为 XML 的那个 JSON对象的属性名。 - 对于
XML to JSON:这里填写包含要解析的 XML字符串的属性名。
- 对于
- 常见错误: 和 HTML 节点类似,新手常在这里误填实际的 XML/JSON 数据,或者使用表达式。正确做法是:使用 “Fixed” 模式,并只填写属性名。例如,如果 XML 字符串在名为
rawData的字段里,这里就填rawData;如果要转换的 JSON 对象在orderData字段里,就填orderData。 - 示例引用: 在一个社区例子中,用户需要转换 Dropbox 下载的 XML 文件,正确的 Property Name 就是 Dropbox 节点输出二进制文件时使用的属性名(默认为
data),而不是使用表达式编辑器去查找变量。
- 极其重要: 这个参数要求你填写包含待转换数据的那个 JSON 属性的名称。
- 处理二进制 XML (Handling Binary XML):
- 关键前提: 如果你的 XML 数据是来自一个二进制文件(例如,通过 HTTP Request 下载了一个
.xml文件,或者从文件系统读取了一个.xml文件),你必须先使用Extract From File 节点将其内容提取为文本。XML 节点本身无法直接处理二进制输入。 - 操作流程:
- 获取文件的节点 (如 HTTP Request, Read Binary File)。
- Extract From File 节点:
- Operation: 选择
Extract From Text File(或者如果确定是 XML,理论上Extract From XML也可以,但转成 Text 更通用)。 - Input Binary Field: 上一步输出二进制数据的字段名 (如
data)。 - Destination Output Field: 给提取出的文本内容起个名字 (如
xmlText)。
- Operation: 选择
- XML 节点:
- Mode:
XML to JSON。 - Property Name: 填写上一步
Extract From File节点输出的文本字段名 (如xmlText)。
- Mode:
- 关键前提: 如果你的 XML 数据是来自一个二进制文件(例如,通过 HTTP Request 下载了一个
- General Options (通用选项):这些选项在两种模式下都可见,但主要影响
XML to JSON的转换结果。- Attribute Key (属性键):
- 默认值:
$。 - 解释:XML 元素可以有属性(如
<item id="123">中的id)。在转换为 JSON 时,为了区分属性和子元素,n8n 默认会将所有属性收集到一个以$符号命名的子对象中。例如,<item id="123" type="mug">Content</item>转换后可能(取决于其他选项)变成类似{"item": { "$": { "id": "123", "type": "mug" }, "_": "Content" }}的结构。这对初学者可能有点奇怪,需要理解$代表属性集合。
- 默认值:
- Character Key (字符键):
- 默认值:
_。 - 解释:当一个 XML 元素既有属性又有文本内容时(或者使用了某些强制显式结构的选项时),其文本内容会被放到一个以
_符号命名的键下。如上例所示,Content就被放在了_键下。如果元素只有文本内容且没有属性,并且未使用强制显式结构,则可能直接是{"item": "Content"}。_的出现通常意味着结构相对复杂。
- 默认值:
- Attribute Key (属性键):
- JSON to XML Specific Options (JSON 转 XML 特定选项):这些选项只在
Mode设置为JSON to XML时出现。- Allow Surrogate Chars (允许代理字符):
- 默认值:Off (关闭)。
- 解释:处理 Unicode 代理对字符。通常保持默认关闭,除非你明确知道需要处理这类特殊字符。
- Cdata (使用 CDATA):
- 默认值:Off (关闭)。
- 解释:CDATA 段 (
<!]>) 在 XML 中用于包裹那些可能包含 XML 特殊字符(如<、&)的文本块,让解析器将其视为纯文本。如果你的 JSON 字段值中包含 HTML 代码或其他需要原样保留在 XML 中的标记文本,可以启用此选项。启用后,节点会在必要时自动用 CDATA 包裹文本。
- Headless (无头部):
- 默认值:Off (关闭)。
- 解释:决定是否在生成的 XML 字符串开头包含 XML 声明
<?xml version="1.0" encoding="UTF-8"?>。有些接收系统需要这个声明,有些则不需要。根据目标系统的要求选择开启或关闭。
- Root Name (根名称):
- 必填项。
- 解释:指定生成的 XML 文档最外层的那个标签(根元素)的名称。例如,如果你要生成一个订单列表的 XML,可以命名为
Orders或OrderList。
- Allow Surrogate Chars (允许代理字符):
- XML to JSON Specific Options (XML 转 JSON 特定选项):这些选项只在
Mode设置为XML to JSON时出现,它们极大地影响了输出 JSON 的结构。- Explicit Array (显式数组):
- 默认值:Off (关闭)。
- 解释:决定如何处理子元素。关闭时:如果一个父元素下只有一个同名子元素,它会直接作为父元素的一个属性;如果 有多个同名子元素,它们会被放入一个数组。开启时:无论有多少个同名子元素(即使只有一个或零个),它们总是被放入一个数组。翔宇的建议:“如果你不确定某个 XML 元素是会出现一次还是多次,建议开启 (ON)’Explicit Array’。这样可以保证数据结构的一致性,后续节点处理起来更方便,不用写复杂的逻辑来判断是单个对象还是数组。”
- Explicit Root (显式根):
- 默认值:On (开启) (文档描述为 On,请以实际节点为准)。
- 解释:决定是否在输出的 JSON 中保留 XML 的根元素作为顶层键。开启时,JSON 结构会是
{ "rootElement": {... } }。关闭时,直接是根元素内部的内容{... }。通常建议保持开启,以维持完整的结构信息。
- Ignore Attributes (忽略属性):
- 默认值:Off (关闭)。
- 解释:开启后,在转换过程中完全丢弃 XML 元素的所有属性,只保留元素名称和文本内容。
- Merge Attributes (合并属性):
- 默认值:Off (关闭)。
- 解释:当 “Ignore Attributes” 关闭时,此选项决定如何处理属性。关闭时:属性被放入
$子对象中。开启时:属性会被提升为与子元素平级的 JSON 属性。例如,<item id="123"><name>Mug</name></item>在开启 Merge Attributes 后可能变成{"item": { "id": "123", "name": "Mug" }}。翔宇的警告:“谨慎使用 ‘Merge Attributes’!如果一个属性名和一个子元素名刚好相同,开启合并会导致其中一个被覆盖,造成数据丢失。默认的$子对象方式虽然看起来复杂一点,但更安全。”
- Normalize (规范化):
- 默认值:Off (关闭)。
- 解释:是否移除 XML 文本节点内部的空白字符(如多余的空格、制表符)。
- Normalize Tags (规范化标签):
- 默认值:Off (关闭)。
- 解释:是否将所有 XML 标签名在转换到 JSON 时统一转换为小写。如果源 XML 的标签大小写不一致,开启此选项可以方便后续处理。
- Trim (修剪):
- 默认值:Off (关闭)。
- 解释:是否移除 XML 文本节点开头和结尾的空白字符(空格、换行、制表符等)。这个通常比较安全,可以开启以获得更干净的文本数据。
为什么 XML 转 JSON 选项这么多?XML 的结构比 JSON 更复杂,它有元素、属性、文本内容这些不同的部分,而 JSON 基本上只有键值对和数组。如何将 XML 的这些不同部分映射到 JSON 的结构中,并没有唯一的标准答案。这些选项提供了不同的映射策略,让用户可以根据自己的需求选择最合适的 JSON 输出结构。例如,默认带$和_的结构最能完整保留 XML 信息,但可能不方便直接使用;而Merge Attributes和Ignore Attributes则可以生成更简洁但可能丢失信息的 JSON。初学者需要理解这些选项是为了在“信息完整性”和“使用便利性”之间找到平衡。
- Explicit Array (显式数组):
3.3 数据映射与流转
XML 节点的数据流转模式如下:
- 输入 (Input):
- JSON to XML: 期望接收一个 n8n 数据项,其
json对象中包含一个由 “Property Name” 指定的属性,该属性的值是要转换为 XML 的 JSON 对象。结构:[{ "json": { "propertyName": { "key": "value", "nested": {... } } } }]。 - XML to JSON: 期望接收一个 n8n 数据项,其
json对象中包含一个由 “Property Name” 指定的属性,该属性的值是待解析的 XML 字符串。结构:[{ "json": { "propertyName": "<root><child>value</child></root>" } }]。再次提醒,如果 XML 来自二进制文件,需要先用 Extract From File 节点处理。
- JSON to XML: 期望接收一个 n8n 数据项,其
- 输出 (Output):
- JSON to XML: 输出一个 n8n 数据项,其中包含一个新字段(通常名为
xml,具体看节点实现),其值为生成的 XML 字符串。结构:[{ "json": {..., "xml": "<root><key>value</key>...</root>" } }]。 - XML to JSON: 输出一个 n8n 数据项,其中包含一个新字段(例如
jsonData或parsedXml,具体看节点实现或可配置),其值为解析后的 JSON 对象。这个 JSON 对象的具体结构严重依赖于你选择的 “XML to JSON Specific Options”。结构示例(取决于选项):[{ "json": {..., "jsonData": { "root": { "child": "value" } } } }]或[{ "json": {..., "jsonData": { "root": { "$": {...}, "_": "...", "child": [...] } } } }]。
- JSON to XML: 输出一个 n8n 数据项,其中包含一个新字段(通常名为
- 数据流位置:
XML to JSON通常紧跟在获取了 XML 数据的节点之后(如 HTTP Request, Read File + Extract From File)。JSON to XML通常位于需要发送 XML 数据的节点(如 HTTP Request)之前,其上游节点(如 Set, Function)负责准备好要转换的 JSON 数据结构。
3.4 工作流实战:XML 节点应用场景
下面通过几个实例,看看 XML 节点如何在实际工作流中发挥作用。
场景 1: 解析 RSS Feed 获取最新文章 目标: 订阅一个博客的 RSS Feed (通常是 XML 格式),提取最新发布的几篇文章的标题和链接。
- 步骤:
- HTTP Request 节点:
- Method:
GET。 - URL: 输入 RSS Feed 的地址 (通常以
.xml或/feed结尾)。 - Response Format:
String或Autodetect(n8n 也许能识别 XML)。
- Method:
- XML 节点:
- Mode:
XML to JSON。 - Property Name:
data(假设 HTTP Request 输出到data字段)。 - Options: 建议开启
Explicit Array,因为 RSS Feed 中的<item>(文章条目) 通常有多个。根据需要调整其他选项(如Trim)。
- Mode:
- (后续处理): 检查 XML 节点输出的 JSON 结构。RSS Feed 的文章通常在
rss.channel.item这样的路径下,并且item是一个数组(因为开启了 Explicit Array)。可以使用Item Lists 节点(Split Out Items) 或Code 节点遍历这个item数组,然后用表达式提取每个item下的title和link字段。
- HTTP Request 节点:
- 翔宇的经验: “RSS Feed 是练习 XML 解析的绝佳材料。转换成 JSON 后,一定要仔细观察输出的数据结构,找到包含文章列表的那个数组路径,才能正确地进行后续提取。”
场景 2: 调用一个需要 XML 输入的 SOAP API 目标: 向一个老旧的 SOAP Web 服务发送请求,请求体必须是特定格式的 XML。 - 步骤:
- (准备数据): 使用Set 节点或Function 节点准备好需要发送的数据,组织成一个符合目标 XML 结构的 JSON 对象(例如
jsonData字段)。 - XML 节点:
- Mode:
JSON to XML。 - Property Name:
jsonData。 - Options:
- Root Name: 设置 SOAP 请求需要的根元素名称 (通常是
soap:Envelope或类似)。 - 根据 SOAP API 的要求,可能需要仔细构造输入的 JSON 结构,以生成包含命名空间 (namespace)、前缀 (prefix) 等复杂结构的 XML。可能需要用到 CDATA 选项。
- Root Name: 设置 SOAP 请求需要的根元素名称 (通常是
- Destination Key:
xmlRequest。
- Mode:
- HTTP Request 节点:
- Method:
POST。 - URL: SOAP 服务的 Endpoint 地址。
- Body Content Type: 选择
application/soap+xml或text/xml(根据 API 文档)。 - Body: 使用表达式
{{ $('XML').item.json.xmlRequest }}将上一步生成的 XML 字符串填入请求体。 - 可能还需要设置特定的 SOAPAction Header。
- Method:
- (准备数据): 使用Set 节点或Function 节点准备好需要发送的数据,组织成一个符合目标 XML 结构的 JSON 对象(例如
- 翔宇的警告: “SOAP API 对 XML 格式的要求非常严格!一个标签、一个属性、一个命名空间不对都可能导致请求失败。你需要非常仔细地阅读 API 文档,然后在 n8n 中构造出能生成完全一致XML 的 JSON 结构。这可能比看起来要复杂,有时甚至需要手动在 JSON 中模拟 XML 的属性 (
$) 和文本 (_) 结构。”
场景 3: 将系统导出的 XML 数据文件转换为 JSON 处理 目标: 处理一个从旧系统中导出的.xml文件,将其中的数据转换为 JSON,以便导入到新的系统或进行分析。 - 步骤:
- Read Binary File 节点: 读取本地的
.xml文件,输出二进制数据到data字段。 - Extract From File 节点:
- Operation:
Extract From Text File。 - Input Binary Field:
data。 - Destination Output Field:
xmlContent。
- Operation:
- XML 节点:
- Mode:
XML to JSON。 - Property Name:
xmlContent。 - Options: 根据 XML 结构调整选项,如
Explicit Array,Trim等。 - Destination Key:
jsonData。
- Mode:
- (后续处理): 使用
jsonData字段中的 JSON 数据进行后续操作,例如使用Google Sheets 节点写入表格,或使用Postgres 节点存入数据库等。
- Read Binary File 节点: 读取本地的
3.5 常见报错与解决方案
使用 XML 节点时,可能会遇到以下问题:
报错: “Invalid character in name” / 解析错误 (Parsing Error) 原因 1: XML 格式本身有问题。
- 对于
XML to JSON:输入的 XML 字符串中包含了无效的字符(如未转义的&)或结构错误(如标签未闭合、嵌套错误)。 - 对于
JSON to XML:输入的 JSON 对象的键名 (key) 包含了 XML 标签名或属性名不允许的字符(最常见的是空格,还有/等)。 - 解决:
- 清理源数据: 确保输入的 XML 是有效的。可以使用在线 XML 验证器(如中提到的)检查 XML 结构。修复源 XML 中的错误,例如将
&替换为&。 - 规范化 JSON 键名: 在进行
JSON to XML转换前,确保 JSON 对象的所有键名都符合 XML 命名规范:不能包含空格,不能以数字或某些符号开头。可以使用 Set 或 Code 节点将键名中的空格替换为下划线_或改用驼峰命名法 (camelCase)。 - 转义内容: 确保 XML 元素或属性的值中,如果包含 XML 特殊字符 (
<,>,&,',"), 它们被正确转义 (如<,>,&,',") 或者使用 CDATA 段包裹。
报错: 节点执行失败或输出为空 原因 1: “Property Name” 参数配置错误,没有指向包含 XML 字符串或 JSON 对象的正确字段名。
- 清理源数据: 确保输入的 XML 是有效的。可以使用在线 XML 验证器(如中提到的)检查 XML 结构。修复源 XML 中的错误,例如将
- 解决: 返回上一步检查输出,确认包含目标数据的字段名,并在 XML 节点的 “Property Name” 中正确填写(使用 Fixed 模式)。
- 原因 2: 尝试直接处理二进制 XML 数据,而没有先使用Extract From File节点。
- 解决: 在 XML 节点之前插入 Extract From File 节点,将二进制内容提取为文本。
报错/问题: 输出的 JSON 结构混乱或不符合预期 原因: 对 XML 转 JSON 的各种选项(如 Explicit Array, Merge Attributes, Attribute Key 等)理解不清,导致默认的转换结果不方便下游节点使用。 - 解决: 回到 “XML to JSON Specific Options” 部分,仔细阅读每个选项的说明。通过开启/关闭这些选项并观察输出 JSON 结构的变化,来找到最适合你后续处理的格式。多做实验是关键。例如,尝试开启
Explicit Array让结构更统一,或者开启Trim和Normalize Tags让数据更干净。 - 翔宇的调试技巧: “处理 XML 转 JSON 时,转换完成后立刻在 n8n 的结果面板中检查输出的 JSON 结构。切换到 Schema 视图或 JSON 视图,仔细看 XML 是如何被翻译的,特别是注意
$(属性) 和_(文本) 的出现位置,以及数组是如何形成的。根据观察到的结果,返回去调整 XML 节点的选项,然后重新测试 (‘Test step’),直到得到的 JSON 结构清晰、易于在后续节点中用表达式(如{{ $json.jsonData.root.items.name }})访问为止。” 同时,利用外部 XML 验证器检查输入 XML 的有效性是个好习惯。如果遇到疑难杂症,可以尝试提高 n8n 的日志级别(通过环境变量N8N_LOG_LEVEL=debug),也许能在日志中看到更详细的 XML 解析错误信息。
3.6 注意事项与最佳实践
最后,分享一些使用 XML 节点的经验和建议:
- 验证输入: 无论是 XML 转 JSON 还是 JSON 转 XML,都要确保输入的数据(XML 字符串或 JSON 键名)符合 XML 的规范和命名规则。无效的输入是导致错误的最常见原因。
- 二进制文件预处理: 牢记:处理来自文件的 XML,必须先用 Extract From File。
- 理解 XML 转 JSON 选项: 不要满足于默认设置。花点时间测试不同的选项组合,找到最适合你需求的 JSON 输出结构。
Explicit Array往往能提升后续处理的稳定性。 - 关注字符编码: 在读取 XML 文件、写入 XML 文件或与 API 交互时,要注意字符编码问题。确保整个流程中使用一致的编码(通常推荐 UTF-8),避免乱码。
- 处理 XML 命名空间 (Namespaces):XML 命名空间(例如
<ns1:root xmlns:ns1="...">)会增加解析和生成的复杂度。n8n 的基础 XML 节点对命名空间的处理能力可能有限。如果遇到带有复杂命名空间的 XML,可能需要更高级的处理,比如在 Code 节点中使用专门的 XML 解析库(但这需要编码知识)。 - 注意大型文件: 处理非常大的 XML 文件可能会消耗大量内存和处理时间。n8n 的核心节点可能不是为流式处理设计的。如果遇到性能瓶颈,可能需要考虑分块处理或其他优化策略(但这超出了基础节点的范畴)。
XML 节点是连接 n8n 与广泛使用 XML 的系统和服务的重要桥梁。掌握它,你的自动化能力将得到显著扩展。
结语
通过这篇深度教程,我们一起系统地学习了 n8n 中处理 HTML、Markdown 和 XML 这三种重要标记语言的核心节点。我们了解了它们各自的功能、详细的参数配置、数据如何在其中流转,并通过实战场景看到了它们的应用价值。同时,我们也分析了常见的报错原因和解决方法,并分享了翔宇在使用过程中的一些经验和最佳实践。
希望现在你对这三个节点不再感到陌生或畏惧。它们是你 n8n 工具箱中强大的武器,能够帮助你轻松应对网页抓取、文本格式化、与各种数据源交互等多种自动化挑战,而这一切,都可以在无需编写代码的前提下实现。
掌握这些节点,无疑会极大地拓宽你使用 n8n 构建自动化工作流的可能性。从监控网页信息,到生成精美报告,再到与传统系统对接,都变得触手可及。
当然,理论学习只是第一步,真正的掌握来自于实践。翔宇强烈建议大家动手去尝试教程中的场景,或者结合自己的实际需求,去创建、去测试、去调试。遇到问题时,不要害怕,回顾教程中的排错部分,利用 n8n 的调试工具,并积极查阅 n8n 官方文档和活跃的社区论坛寻求帮助。
最后寄语:“自动化是一个持续学习和探索的旅程。从简单的开始,理解你的数据,细致地测试,遇到困难时不要放弃,社区里有很多乐于助人的人。HTML、Markdown 和 XML 节点是你旅途中不可或缺的伙伴,善用它们,你的自动化之路将越走越宽广!”
感谢你的阅读,希望这篇教程能对你有所帮助。祝你在 n8n 的世界里创造出更多精彩的工作流!
