2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类

1. 思路

  1. 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。
  2. 引入工具类 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. 测试

测试结果

image-20250126155507486

image-20250126155201114

image-20250126155245693

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### 三方服务无 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8641.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Pytest】生成html报告中,中文乱码问题解决方案

import pytestif __name__ "__main__":# 只运行 tests 目录下的测试用例&#xff0c;并生成 HTML 报告pytest.main([-v, -s, --htmlreport.html, tests])可以以上方式生成&#xff0c;也可以在pytest.ini中设置 [pytest] addopts --htmlreport.html --self-contai…

Couchbase UI: Views

Couchbase 的 Views 页面是用于创建和管理视图的部分&#xff0c;视图是一种用于从 Couchbase 中提取和聚合数据的机制。视图通常用于实现简单的查询和数据汇总&#xff0c;特别是在处理大数据集时。以下是关于 Couchbase Views 页面的详细说明。 Views 页面功能概述 视图创建…

SpringBoot+Electron教务管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.查询课程表代码2.保存学生信息代码3.用户登录代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootElectron框架开发的教务管理系统。首先&#xff…

mysql索引 a

2.1 索引概述 2.1.1 介绍 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统还维护着满足 特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c; 这样就…

HTML5+SVG+CSS3实现雪中点亮的圣诞树动画效果源码

源码介绍 这是一款基于HTML5SVGCSS3实现雪中点亮的圣诞树动画效果源码。画面中的圣诞树矗立在雪地中&#xff0c;天上飘落着雪花。当鼠标滑过圣诞树时&#xff0c;可见到圣诞树上的灯光闪烁&#xff0c;同时左下角探出雪怪模样的半个脑袋&#xff0c;四处张望着。整体画面栩栩…

DeepSeek API 的获取与对话示例

代码文件下载&#xff1a;Code 在线链接&#xff1a;Kaggle | Colab 文章目录 注册并获取API环境依赖设置 API单轮对话多轮对话流式输出更换模型 注册并获取API 访问 https://platform.deepseek.com/sign_in 进行注册并登录&#xff1a; 新用户注册后将赠送 10 块钱余额&#…

Spark Streaming编程基础

文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用&#xff0c;查看结果 2. 编程模型的基本概念2…

JavaScript中的隐式类型转换

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

React第二十六章(createPortal)

createPortal 注意这是一个API&#xff0c;不是组件&#xff0c;他的作用是&#xff1a;将一个组件渲染到DOM的任意位置&#xff0c;跟Vue的Teleport组件类似。 用法 import { createPortal } from react-dom;const App () > {return createPortal(<div>小满zs<…

Linux学习笔记——磁盘管理命令

lsblk(list block devices):其功能是查看系统的磁盘使用情况 df(disk free):列出文件系统的整体磁盘使用量 du(disk used):检查磁盘空间使用量 fdisk:用于磁盘分区&#xff08;创建分区&#xff09; mkfs:创建并构建一个文件系统&#xff08;格式化&#xff09; mount:挂在…

QT使用eigen

QT使用eigen 1. 下载eigen https://eigen.tuxfamily.org/index.php?titleMain_Page#Download 下载后解压 2. QT引入eigen eigen源码好像只有头文件&#xff0c;因此只需要引入头文件就好了 qt新建项目后。修改pro文件. INCLUDEPATH E:\222078\qt\eigen-3.4.0\eigen-3.…

国内优秀的FPGA设计公司主要分布在哪些城市?

近年来&#xff0c;国内FPGA行业发展迅速&#xff0c;随着5G通信、人工智能、大数据等新兴技术的崛起&#xff0c;FPGA设计企业的需求也迎来了爆发式增长。很多技术人才在求职时都会考虑城市的行业分布和发展潜力。因此&#xff0c;国内优秀的FPGA设计公司主要分布在哪些城市&a…

Linux——rzsz工具

rzsz这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件. 安装完毕之后可以通过拖拽的方式将文件上传过去. 安装rzsz工具 rz&#xff1a;从Windows机器上传到远程Linux机器&#xff08;或者直接把文件托进Xshell中&#xff09; sz&#xff1a;将文件从Linux远…

【linux网络(3)】应用层HTTP协议详解

目录 前言1. 序列化和反序列化2. 认识URL3. 对网络中资源的理解4. HTTP的报文格式5. HTTP方法详解6. HTTP的状态码和header7. HTTP会话管理8. 总结以及拓展 前言 在理解了网络套接字编程后, 后续的文章会从应用层到链路层, 详解的讲解每一层的协议都做了些什么工作, 并且会拆分…

利用JSON数据类型优化关系型数据库设计

利用JSON数据类型优化关系型数据库设计 前言 在关系型数据库中&#xff0c;传统的结构化存储方式要求预先定义好所有的列及其数据类型。 然而&#xff0c;随着业务的发展&#xff0c;这种设计可能会显得不够灵活&#xff0c;尤其是在需要扩展单个列的描述功能时。 JSON数据…

cursor ide配置远程ssh qt c++开发环境过程记录

cursor是啥就不介绍了&#xff0c;好像是目前最好用的ai ide&#xff0c;下面主要是配置远程ssh连接linux机器进行qt5 c程序运行的配置过程记录。 一、c_cpp_properties.json 在项目根目录的.vscode目录里面新建c_cpp_properties.json文件&#xff0c;根据你的实际情况配置该文…

npm:升级自身时报错:EBADENGINE

具体报错信息如下&#xff1a; 1.原因分析 npm和当前的node版本不兼容。 // 当前实际版本: Actual: {"npm":"10.2.4","node":"v20.11.0"}可以通过官网文档查看与自己 node 版本 兼容的是哪一版本的npm&#xff0c;相对应进行更新即可…

Excel中LOOKUP函数的使用

文章目录 VLOOKUP&#xff08;垂直查找&#xff09;&#xff1a;HLOOKUP&#xff08;水平查找&#xff09;&#xff1a;LOOKUP&#xff08;基础查找&#xff09;&#xff1a;XLOOKUP&#xff08;高级查找&#xff0c;较新版本Excel提供&#xff09;&#xff1a; 在Excel中&…

Verilog中if语句和case语句综合出的电路区别

区别是 if else 的逻辑判断有优先级&#xff0c;最内层的 if 的优先级最高&#xff0c;case 的逻辑判断是并列的。 每个 if else 综合出来的电路是一个 2 选 1 选通器。当信号有明显优先级时使用该语句&#xff0c;但是 if 嵌套太多的话会导致路径延时过大&#xff0c;降低运行…

【C语言常见概念详解】

目录 -----------------------------------------begin------------------------------------- 什么是C语言&#xff1a; 1. 基本数据类型 2. 变量与常量 3. 运算符与表达式 4. 控制结构 5. 函数 6. 指针 7. 数组与字符串 8. 结构体与联合体 9. 文件操作 结语 ----…