将Markdown内容转换为XML格式
技术百科
星降
发布时间:2026-01-20
浏览: 次 Markdown转XML无统一标准,必须先明确目标XML结构和用途;不能直接用markdown-it或marked,因其不保证XML良构性;推荐用remark-parse解析为AST后,以xmlbuilder2按需构建XML。
Markdown 转 XML 没有统一标准,必须先明确目标 XML 的结构和用途——是用于文档归档(如 DocBook)、网页渲染(如 XHTML),还是自定义数据交换格式?直接套用通用转换器大概率会失败。
为什么不能用 markdown-it 或 marked 直接生成 XML?
这些库默认输出 HTML 字符串,即使开启 html: false 也只是禁用内联 HTML 标签,仍会保留非 XML 兼容的转义(如 )或缺失 XML 声明与根元素。更关键的是:它们不校验标签闭合、不处理命名空间、也不保证属性值被双引号包裹——而这些都是良构 XML 的硬性要求。
用 xmlbuilder2 + 手动解析 Markdown AST 最可靠
推荐流程:用 remark-parse 解析 Markdown 为

unist 树),再遍历节点,用 xmlbuilder2 构建符合你 Schema 的 XML。这样能完全控制每个节点的映射逻辑,比如:
-
heading节点 →或,取决于你的 DTD -
list节点 → 强制用/,而非自定义 -
inlineCode→ 包裹在中,而非裸文本
示例片段(将一级标题转为 ):
const { remark } = await import('remark');
const { xml } = await import('xmlbuilder2');
const md = '# Hello World';
const tree = (await remark().use(() => {}).parse(md));
const doc = xml({ version: '1.0', encoding: 'UTF-8' });
const root = doc.ele('document');
function walk(node) {
if (node.type === 'heading' && node.depth === 1) {
const title = node.children[0]?.value || '';
root.ele('doc-title').txt(title);
}
}
walk(tree);
console.log(doc.end({ prettyPrint: true }));
// 输出:
//
//
// Hello World
//
警惕 pandoc 的隐式行为
pandoc -f markdown -t docbook 看似便捷,但它依赖内置模板,且:
- 会自动插入
、等语义化标签,无法关闭 - 对中文标点、脚注、自定义容器(如 :::warning)支持不稳定
- 输出含
xmlns和role属性,若下游系统不认这些命名空间,解析会报错
如果只是临时导出,加 --wrap=none --standalone 可减少干扰;但生产环境建议绕过 pandoc,走 AST 路线。
真正难的不是语法转换,而是决定每个 Markdown 语义单元对应哪个 XML 元素——这个映射规则一旦定错,后续所有 XSLT 或 XPath 都得重写。
# ai
# 的是
# 也不
# 重写
# markdown
# 自定义
# 而非
# 不稳定
# 必须先
# class
# html
# xml
# 字符串
# 报错
# 为什么
# node
# 命名空间
# 遍历
# 不能用
# ul
# xhtml
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- php怎么下载安装后设置默认字符集_utf8配置步
- 如何使用正则表达式批量替换重复的星号-短横模式为固
- Mac版Final Cut Pro入门_Mac视频
- 如何使用Golang读取日志文件_Golang b
- Win11怎么清理C盘下载文件夹_Win11清理下
- Win10系统怎么查看显卡温度_Win10任务管理
- Win11怎么关闭触摸键盘图标_Windows11
- Win11怎么开启远程桌面_Win11系统远程桌面
- Win10系统怎么查看网络连接状态_Windows
- 如何用正则表达式精确匹配最多含一个换行符的起止片段
- Win11怎么设置开机问候语_自定义Win11锁屏
- 如何在 Go 中创建包含 map 的 slice(
- Windows10电脑怎么设置电源按钮_Win10
- Windows11怎么自定义任务栏_Windows
- Win10电脑C盘红了怎么清理_Windows10
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- Python函数参数高级用法_默认值与可变参数解析
- Windows电脑如何进入安全模式?(多种按键方法
- c++协程和线程的区别 c++异步编程模型对比【核
- Windows笔记本无法进入睡眠模式怎么办?(电源
- Win11怎么关闭边缘滑动手势_Windows11
- 如何使用 Selenium 正确获取篮球参考网站球
- windows如何测试网速_windows系统网络
- Python爬虫项目实战教程_Scrapy抓取与存
- PythonGIL机制理解_多线程限制解析【教程】
- Mac的“调度中心”与“空间”怎么用_Mac多桌面
- php怎么下载安装并配置环境变量_命令行调用PHP
- Python 中将 ISO 8601 时间戳转换为
- Windows怎样拦截QQ浏览器广告_Window
- 如何使用Golang实现容器健康检查_监控和自动重
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Mac怎么给文件夹加密_Mac创建加密磁盘映像教程
- C++如何使用std::async进行异步编程?(
- php查询数据怎么导出csv_查询结果转csv文件
- php删除数据怎么清空表_truncate与del
- Windows10无法连接到Internet_Wi
- 如何使用Golang实现错误包装与传递_Golan
- Python异步编程高级项目教程_asyncio协
- php订单日志怎么记录评价_php记录订单评价日志
- 如何在Windows中创建新的用户账户?(标准与管
- Win11怎么更改计算机名_Windows11系统
- 如何使用Golang实现云原生应用弹性伸缩_自动应
- php8.4如何调用com组件_php8.4win
- 如何在Golang中编写异步函数测试_Golang
- PHP 中如何在函数内持久修改引用变量所指向的目标
- Win11开机自检怎么关闭_跳过Win11开机磁盘
- 本地php环境出现502错误_nginx或apac
- c# 如何用c#实现一个支持优先级的任务队列
- Python邮件系统自动化教程_批量发送解析与模板
- php下载安装选zip还是msi格式_两种安装包对

QQ客服