2. Java-MarkDown文件解析-工具类
2. Java-MarkDown文件解析-工具类
1. 思路
- 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。
- 引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。
2. 工具类
pom.xml
<!-- commonmark 解析markdown -->
<dependency><groupId>org.commonmark</groupId><artifactId>commonmark</artifactId><version>0.21.0</version>
</dependency>
<!-- commonmark 解析markdown tables -->
<dependency><groupId>org.commonmark</groupId><artifactId>commonmark-ext-gfm-tables</artifactId><version>0.21.0</version>
</dependency>
MarkdownParseResult
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** Markdown解析结果* @Author: onecomer* @Date: 2021/1/26 16:00*/
@ApiModel(description = "Markdown解析结果")
@Data
public class MarkdownParseResult {@ApiModelProperty(value = "MarkdownHtml内容")private String htmlContent;@ApiModelProperty(value = "标题及内容集合",example = "{'标题1':'内容1','标题2':'内容2',...}")private JSONObject titles;@ApiModelProperty(value = "表格标题及内容集合",example = "{'表格标题':'{headers:['列1','列2'],rows:[{'值1','值2'},{'值1','值2'}]}",notes = "headers为表头,rows为行数据")private JSONObject tables;@ApiModelProperty(value = "无序列表集合",example = "{''无序列表标题:[{'无序列表内容1'},{'无序列表内容2'},...]}")private JSONObject unOrderedLists;@ApiModelProperty(value = "有序列表集合",example = "{''有序列表标题:[{'有序列表内容1'},{'有序列表内容2'},...]}")private JSONObject orderedLists;@ApiModelProperty(value = "代码块集合",example = "{'代码块标题1':{'codeBlockContent(固定值)':'代码块内容1','codeBlockType(固定值)':'代码块类型1'}}")private JSONObject codeBlocks;
}
MarkdownParserUtil
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TableBody;
import org.commonmark.ext.gfm.tables.TableCell;
import org.commonmark.ext.gfm.tables.TableHead;
import org.commonmark.ext.gfm.tables.TableRow;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.AbstractVisitor;
import org.commonmark.node.BulletList;
import org.commonmark.node.FencedCodeBlock;
import org.commonmark.node.Heading;
import org.commonmark.node.ListItem;
import org.commonmark.node.Node;
import org.commonmark.node.OrderedList;
import org.commonmark.node.Paragraph;
import org.commonmark.node.SoftLineBreak;
import org.commonmark.node.Text;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Markdown解析工具类* @Author: onecomer* @Date: 2021/1/26 16:00*/
public class MarkdownParserUtil {private static Parser parser;private static HtmlRenderer renderer;static {parser = Parser.builder().extensions(Arrays.asList(TablesExtension.create())).build();renderer = HtmlRenderer.builder().extensions(Arrays.asList(TablesExtension.create())).build();}/*** 读取并解析Markdown文件*/public static MarkdownParseResult parseMarkdownFile(String filePath) {String content = null;try {content = new String(Files.readAllBytes(Paths.get(filePath)));} catch (IOException e) {throw new RuntimeException(e);}MarkdownParseResult result = parseMarkdownFileContent(content);return result;}/*** 解析Markdown内容*/public static MarkdownParseResult parseMarkdownFileContent(String content) {Node document = parser.parse(content);MarkdownParseResult result = new MarkdownParseResult();
// result.setHtmlContent(renderer.render(document));JSONObject titles = new JSONObject(true);JSONObject tables = new JSONObject(true);JSONObject unOrderedLists = new JSONObject(true);JSONObject orderedLists = new JSONObject(true);JSONObject codeBlocks = new JSONObject(true);String currentHeading = "";StringBuilder paragraphContent = new StringBuilder();boolean isDelReapeatTilte = true;Node node = document.getFirstChild();while (node != null) {if (node instanceof Heading) {// 标题String text = getText(node);currentHeading = text;// 只有标题的直接添加if (!((node.getNext()) instanceof Paragraph)) {titles.put(currentHeading, currentHeading);}} else if (node instanceof Paragraph) {String text = getText(node);// 普通文本paragraphContent.append(text).append("\n");// 结束添加paragraphContentif (!((node.getNext()) instanceof Paragraph)) {titles.put(currentHeading, paragraphContent.toString().trim());paragraphContent = new StringBuilder();}} else if (node instanceof BulletList) {// 无序列表JSONArray items = new JSONArray();Node listItem = node.getFirstChild();while (listItem != null) {if (listItem instanceof ListItem) {String text = getText(listItem);items.add(text);}listItem = listItem.getNext();}unOrderedLists.put(currentHeading, items);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof OrderedList) {// 有序列表JSONArray items = new JSONArray();Node listItem = node.getFirstChild();while (listItem != null) {if (listItem instanceof ListItem) {String text = getText(listItem);items.add(text);}listItem = listItem.getNext();}orderedLists.put(currentHeading, items);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof FencedCodeBlock) {// 代码块FencedCodeBlock codeBlock = (FencedCodeBlock) node;JSONObject codeBlockInfo = new JSONObject(true);String codeBlockContent = codeBlock.getLiteral();String codeBlockType = codeBlock.getInfo();codeBlockInfo.put("codeBlockContent", codeBlockContent);codeBlockInfo.put("codeBlockType", codeBlockType);codeBlocks.put(currentHeading, codeBlockInfo);if (isDelReapeatTilte) {titles.remove(currentHeading);}} else if (node instanceof TableBlock) {// 表格JSONObject tableInfo = new JSONObject(true);JSONArray headers = new JSONArray();JSONArray rows = new JSONArray();// TableHeadNode row = node.getFirstChild();if (row instanceof TableHead) {Node headerRow = row.getFirstChild();if (headerRow instanceof TableRow) {Node cell = headerRow.getFirstChild();while (cell != null) {if (cell instanceof TableCell) {String text = getText(cell);headers.add(text);}cell = cell.getNext();}}}// TableBodyNode tableBody = row.getNext();while (tableBody != null) {if (tableBody instanceof TableBody) {// TableRowNode tableRow = tableBody.getFirstChild();while (tableRow != null) {if (tableRow instanceof TableRow) {JSONArray rowData = new JSONArray();Node tableCell = tableRow.getFirstChild();while (tableCell != null) {if (tableCell instanceof TableCell) {String text = getText(tableCell);rowData.add(text);}tableCell = tableCell.getNext();}rows.add(rowData);}tableRow = tableRow.getNext();}}tableBody = tableBody.getNext();}tableInfo.put("headers", headers);tableInfo.put("rows", rows);tables.put(currentHeading, tableInfo);if (isDelReapeatTilte) {titles.remove(currentHeading);}}// 处理下一个节点node = node.getNext();}result.setTitles(titles);result.setTables(tables);result.setUnOrderedLists(unOrderedLists);result.setOrderedLists(orderedLists);result.setCodeBlocks(codeBlocks);return result;}/*** 获取节点的文本内容(包含格式)*/private static String getText(Node node) {StringBuilder sb = new StringBuilder();node.accept(new AbstractVisitor() {@Overridepublic void visit(Text text) {sb.append(text.getLiteral());}// @Override
// public void visit(Emphasis emphasis) {
// sb.append("*").append(getText(emphasis)).append("*");
// }
//
// @Override
// public void visit(StrongEmphasis strongEmphasis) {
// sb.append("**").append(getText(strongEmphasis)).append("**");
// }
//
// @Override
// public void visit(Code code) {
// sb.append("`").append(code.getLiteral()).append("`");
// }});return sb.toString().trim();}/*** 判断是否为表格节点*/@Deprecatedprivate static boolean isTable(Node node) {
// String content = getTextContent(node);
// return content.contains("|") && content.contains("\n") && content.contains("---");Node firstChild = node.getFirstChild();Node secondChild = firstChild != null ? firstChild.getNext() : null;if (secondChild instanceof SoftLineBreak) {return true;}return false;}/*** 解析表格内容*/@Deprecatedprivate static JSONObject parseTable(Node tableNode) {String[] lines = getText(tableNode).split("\n");boolean isHeader = true;List<String> headers = new ArrayList<>();for (String line : lines) {line = line.trim();if (line.isEmpty() || line.startsWith("|---")) {isHeader = false;continue;}String[] cells = line.split("\\|");List<String> cleanCells = new ArrayList<>();for (String cell : cells) {String cleaned = cell.trim();if (!cleaned.isEmpty()) {cleanCells.add(cleaned);}}if (isHeader) {headers.addAll(cleanCells);
// tableInfo.setHeaders(headers);} else {Map<String, String> row = new HashMap<>();for (int i = 0; i < headers.size() && i < cleanCells.size(); i++) {row.put(headers.get(i), cleanCells.get(i));}
// tableInfo.getRows().add(row);}}return null;}public static void main(String[] args) {String filePath = "D:\\tab\\1_ideaIC-2022.2.win\\2_WS\\1_SAAS_hgit_2\\2_assembler_all\\3_biz-project\\api-manage\\markdown\\新增实体数据能力.md";
// filePath = "D:\\tab\\1_ideaIC-2022.2.win\\2_WS\\1_SAAS_hgit_2\\2_assembler_all\\3_biz-project\\api-manage\\markdown\\新增实体数据能力2.md";MarkdownParseResult result = parseMarkdownFile(filePath);// System.out.println("HTML内容:");
// System.out.println(result.getHtmlContent());System.out.println("\n标题及内容:");System.out.println(result.getTitles().toJSONString());System.out.println("\n表格内容:");System.out.println(result.getTables().toJSONString());System.out.println("\n无序列表:");System.out.println(result.getUnOrderedLists().toJSONString());System.out.println("\n有序列表:");System.out.println(result.getOrderedLists().toJSONString());System.out.println("\n代码块:");System.out.println(result.getCodeBlocks().toJSONString());}
}
3. 测试
测试结果




markdown文件
# 新增实体数据能力## 接口说明用来新增一条记录用来新增一条记录2用来新增一条记录3## 资产类型:API## 应用- 应用S码:Sxx## 标签- 新增实体数据能力
- xxx系统
- Sxx
- 新增记录 数据管理## 版本- v1.0.0## 接口地址```json
{"测试地址": "{baseUrl}/model/{dataSource}/{entityName}/add","生产地址": "{baseUrl}/model/{dataSource}/{entityName}/add"
}
```## 调用前提```json
需要先部署低代码引擎微服务,部署文档链接如下:
开发环境引擎部署:https://ihaier.feishu.cn/wiki/LyitwBYg4i8fRDkpPC0crxpMnlg
运行环境引擎部署:https://ihaier.feishu.cn/wiki/ZG16wdmOiib658k39X1cuzlKnSe
```## 请求方式POST## 请求头Header| 参数名 | 类型 | 是否必填 | 参数说明 |
| :----------- | :----- | :------- | :---------------------------- |
| Access-Token | String | 是 | 统一登录token,从账号中心获取 |
| Access-Token2 | String | 是 | 统一登录token,从账号中心获取 |## 请求参数类型@RequestBody## 请求参数| 参数名 | 是否必填 | 类型 | 描述 |
| :--------- | :------- | :----------- | :---------------------- |
| field1 | 否 | String | 字段1 |
| field2 | 否 | Integer | 字段2 |
| entityName | 否 | Object/Array | 关联实体(一对一/一对多) |### 请求参数示例```json
{"field1": "","field2": 19,"entityName": {"field1": "","field2": ""},"entityName": [{"field1": "","field2": ""}]
}
```## 返回参数类型@ResponseBody## 返回参数| 参数名 | 类型 | 说明 |
| :------ | :------ | :--------------------------- |
| code | Integer | 响应码,0表示成功,非0表示失败 |
| message | String | 提示消息 |
| data | Object | 返回数据 |
| data.id | String | 主键ID |### 返回参数示例#### 正确```json
{"code": 0,"message": "success", "data": {"id": "主键ID"}
}
```#### 错误```json
{"code": 400,"message": "请求参数错误"
}
```### 错误码| errorCode | errorMessage |
| :-------- | :----------- |
| 400 | 请求参数错误 |## 调用示例```json
// 请求示例
POST /model/myDataSource/User/add
{"name": "张三","age": 25,"department": {"id": "dept001","name": "技术部"}
}// 返回结果示例
{"code": 0,"message": "success","data": {"id": "user001"}
}
```## 实现逻辑### 时序图```mermaid
sequenceDiagramparticipant Clientparticipant APIparticipant Serviceparticipant DatabaseClient->>API: POST /model/{ds}/{entity}/addAPI->>Service: addEntity(data)Service->>Service: validateData(data)Service->>Database: insert(data)Database-->>Service: Return idService-->>API: Return resultAPI-->>Client: Return response
```### 业务逻辑1. 校验请求参数的合法性
2. 根据实体定义验证字段
3. 生成主键ID
4. 保存实体数据
5. 返回新增记录的ID### 三方服务无
相关文章:
2. Java-MarkDown文件解析-工具类
2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...
threejs实现烟花效果
大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...
ThinkPad E480安装Ubuntu 18.04无线网卡驱动
个人博客地址:ThinkPad E480安装Ubuntu 18.04无线网卡驱动 | 一张假钞的真实世界 遗憾的是虽然下面的方法可以解决,但是内核升级后需要重新安装。 基本信息 Ubuntu 18.04ThinkPad E480使用下面的命令查看 Linux 内核: $ uname -r 5.0.0-3…...
React Router v6配置路由守卫
首先准备好以下页面 登录页:用户可以在此页面登录。 受保护页:只有登录的用户可以访问,否则会重定向到登录页。 公共页面:不需要鉴权,任何人都可以访问。 1. 安装依赖 首先,我们需要安装 react-router-do…...
研发的立足之本到底是啥?
0 你的问题,我知道! 本文深入T型图“竖线”的立足之本:专业技术 技术赋能业务能力。研发在学习投入精力最多,也误区最多。 某粉丝感发展遇到瓶颈,项目都会做,但觉无提升,想跳槽。于是&#x…...
react中如何获取dom元素
实现代码 const inputRef useRef(null) inputRef.current.focus()...
JavaScript系列(49)--游戏引擎实现详解
JavaScript游戏引擎实现详解 🎮 今天,让我们深入探讨JavaScript的游戏引擎实现。游戏引擎是一个复杂的系统,它需要处理渲染、物理、音频、输入等多个方面,让我们一步步实现一个基础但功能完整的游戏引擎。 游戏引擎基础概念 &am…...
20【变量的深度理解】
一说起变量,懂点编程的都知道,但是在理解上可能还不够深 变量就是存储空间,电脑上的存储空间有永久(硬盘)和临时(内存条)两种,永久数据重启电脑后依旧存在,临时数据只…...
19.Word:小马-校园科技文化节❗【36】
目录 题目 NO1.2.3 NO4.5.6 NO7.8.9 NO10.11.12索引 题目 NO1.2.3 布局→纸张大小→页边距:上下左右插入→封面:镶边→将文档开头的“黑客技术”文本移入到封面的“标题”控件中,删除其他控件 NO4.5.6 标题→原文原文→标题 正文→手…...
DeepSeek回答量化策略对超短线资金的影响
其实最近很长一段时间我在盘中的感受就是量化策略的触发信号都是超短线选手经常用到的,比如多个题材相互卡位,近期小红书-消费,好想你,来伊份 跟 算力 电光科技,机器人 金奥博 冀凯股份 五洲新春 建设工业 ,这些票的波动其实都是被量化策略锚定了,做成了策略异动。特别…...
2.3.1 基本数据类型
ST(Structured Text)语言支持多种基本数据类型,用于定义变量、常量以及函数参数等。这些数据类型涵盖了布尔值、整数、浮点数、字符和字符串等常见类型。以下是ST语言中基本数据类型的详细说明: 布尔类型(BOOL…...
探秘 TCP TLP:从背景到实现
回家的路上还讨论了个关于 TCP TLP 的问题,闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。 TLP,先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO…...
解锁豆瓣高清海报:深度爬虫与requests进阶之路
前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,并自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我看过的影视 界面找到图片…...
无耳科技 Solon v3.0.7 发布(2025农历新年版)
Solon 框架! Solon 框架由杭州无耳科技有限公司(下属 Noear 团队)开发并开源。是新一代,面向全场景的 Java 企业级应用开发框架。从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态。…...
常见的多媒体框架(FFmpeg GStreamer DirectShow AVFoundation OpenMax)
1.FFmpeg FFmpeg是一个非常强大的开源多媒体处理框架,它提供了一系列用于处理音频、视频和多媒体流的工具和库。它也是最流行且应用最广泛的框架! 官方网址:https://ffmpeg.org/ FFmpeg 的主要特点和功能: 编解码器支持: FFmpe…...
本地部署Deepseek R1
最近Deepseek R1模型也是彻底火出圈了, 但是线上使用经常会受到各种限制,有时候还会连不上,这里我尝试本地部署了Deepseek 的开源R1模型,具体的操作如下: 首先登陆ollama平台,Ollama.ollama平台是一个开源…...
深入解析 .NET 命名管道技术, 通过 Sharp4Tokenvator 实现本地权限提升
01. 管道访问配置 在 .NET 中通常使用 PipeSecurity 类为管道设置访问控制规则,用于管理命名管道的访问控制列表(ACL)。通过这个类,可以为命名管道配置精细化的安全权限,从而控制哪些用户或用户组能够访问管道&#x…...
Cesium ArcGisMapServerImageryProvider API 介绍
作为一名GIS研究生,WebGIS 技术无疑是我们必学的核心之一。说到WebGIS,要提的就是 Cesium —— 这个让3D地球可视化变得简单又强大的工具。为了帮助大家更好地理解和使用 Cesium,我决定把我自己在学习 Cesium 文档过程中的一些心得和收获分享…...
登录授权流程
发起一个网络请求需要:1.请求地址 2.请求方式 3.请求参数 在检查中找到request method,在postman中设置同样的请求方式将登录的url接口复制到postman中(json类型数据)在payload中选择view parsed,将其填入Body-raw中 …...
Python设计模式 - 组合模式
定义 组合模式(Composite Pattern) 是一种结构型设计模式,主要意图是将对象组织成树形结构以表示"部分-整体"的层次结构。这种模式能够使客户端统一对待单个对象和组合对象,从而简化了客户端代码。 组合模式有透明组合…...
【深度学习】图像分类数据集
图像分类数据集 MNIST数据集是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集。 %matplotlib inline import torch import torchvision from torch.utils import data from torchvision import transfo…...
【四川乡镇界面】图层shp格式arcgis数据乡镇名称和编码2020年wgs84无偏移内容测评
本文将详细解析标题和描述中提到的IT知识点,主要涉及GIS(Geographic Information System,地理信息系统)技术,以及与之相关的文件格式和坐标系统。 我们要了解的是"shp"格式,这是一种广泛用于存储…...
ubuntu解决普通用户无法进入root
项目场景: 在RK3566上移植Ubuntu20.04之后普通用户无法进入管理员模式 问题描述 在普通用户使用sudo su试图进入管理员模式的时候报错 解决方案: 1.使用 cat /etc/passwd 查看所有用户.最后一行是 若无用户,则使用 sudo useradd -r -m -s /…...
数据结构选讲 (更新中)
参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的: AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树,点有点权 w i w_i wi,边有边权。建立…...
freeswtch目录下modules.conf各个模块的介绍【freeswitch版本1.6.8】
应用模块(applications) mod_abstraction: 为其他模块提供抽象层,有助于简化模块开发,让开发者能在统一框架下开发新功能,减少与底层系统的直接交互,提高代码可移植性和可维护性。 mod_av&#…...
第3章 基于三电平空间矢量的中点电位平衡策略
0 前言 在NPC型三电平逆变器的直流侧串联有两组参数规格完全一致的电解电容,由于三电平特殊的中点钳位结构,在进行SVPWM控制时,在一个完整开关周期内,直流侧电容C1、C2充放电不均匀,各自存储的总电荷不同,电容电压便不均等,存在一定的偏差。在不进行控制的情况下,系统无…...
网络工程师 (8)存储管理
一、页式存储基本原理 (一)内存划分 页式存储首先将内存物理空间划分成大小相等的存储块,这些块通常被称为“页帧”或“物理页”。每个页帧的大小是固定的,例如常见的页帧大小有4KB、8KB等,这个大小由操作系统决定。同…...
Shell特殊位置变量以及常用内置变量总结
目录 1. 特殊的状态变量 1.1 $?(上一个命令的退出状态) 1.2 $$(当前进程的 PID) 1.3 $!(后台进程的 PID) 1.4 $_(上一条命令的最后一个参数) 2.常用shell内置变量 2.1 echo&…...
实验一---典型环节及其阶跃响应---自动控制原理实验课
一 实验目的 1.掌握典型环节阶跃响应分析的基本原理和一般方法。 2. 掌握MATLAB编程分析阶跃响应方法。 二 实验仪器 1. 计算机 2. MATLAB软件 三 实验内容及步骤 利用MATLAB中Simulink模块构建下述典型一阶系统的模拟电路并测量其在阶跃响应。 1.比例环节的模拟电路 提…...
基于 WEB 开发的在线考试系统设计与实现
标题:基于 WEB 开发的在线考试系统设计与实现 内容:1.摘要 基于 WEB 开发的在线考试系统旨在提供一个便捷、高效、公平的考试环境。本文详细介绍了该系统的设计与实现过程,包括系统架构、功能模块、数据库设计等方面。通过实际应用,证明了该系统具有良好…...
