Java提取markdown中的表格

Java提取markdown中的表格

说明

这篇博文是一个舍近求远的操作,如果只需要要对markdown中的表格数据进行提取,完全可以通过正在表达式或者字符串切分来完成。但是鉴于学习的目的,这次采用了commonmark包中的工具来完成。具体实现过程如下

实现步骤

引入pom依赖

		<dependency>
            <groupId>org.commonmark</groupId>
            <artifactId>commonmark</artifactId>
            <version>0.21.0</version>
        </dependency>
        <dependency>
            <groupId>org.commonmark</groupId>
            <artifactId>commonmark-ext-gfm-tables</artifactId>
            <version>0.21.0</version>
        </dependency>

自定义vistor

import org.commonmark.ext.gfm.tables.*;
import org.commonmark.node.*;

import java.util.ArrayList;
import java.util.List;

public class TableVisitor extends AbstractVisitor {
    private boolean inHeader = false;
    private boolean inBody = false;
    private List<String> currentRow = null;

    private List<String> headers = new ArrayList<>();

    private final List<List<String>> rows = new ArrayList<>();

    @Override
    public void visit(CustomBlock customBlock) {
        if (customBlock instanceof TableBlock) {
            handleTableBlock((TableBlock) customBlock);
        } else {
            super.visit(customBlock);
        }
    }

    @Override
    public void visit(CustomNode customNode) {
        if (customNode instanceof TableHead) {
            handleTableHead((TableHead) customNode);
        } else if (customNode instanceof TableBody) {
            handleTableBody((TableBody) customNode);
        } else if (customNode instanceof TableRow) {
            handleTableRow((TableRow) customNode);
        } else if (customNode instanceof TableCell) {
            handleTableCell((TableCell) customNode);
        } else {
            super.visit(customNode);
        }
    }

    private void handleTableBlock(TableBlock tableBlock) {
        // 重置状态
        inHeader = false;
        inBody = false;
        visitChildren(tableBlock);
    }

    private void handleTableHead(TableHead tableHead) {
        inHeader = true;
        visitChildren(tableHead);
        inHeader = false;
    }

    private void handleTableBody(TableBody tableBody) {
        inBody = true;
        visitChildren(tableBody);
        inBody = false;
    }

    private void handleTableRow(TableRow tableRow) {
        currentRow = new ArrayList<>();
        visitChildren(tableRow);

        if (inHeader) {
            this.headers = currentRow;
        } else if (inBody) {
            this.rows.add(currentRow);
        }
    }

    private void handleTableCell(TableCell tableCell) {
        if (currentRow != null) {
            currentRow.add(getTextContent(tableCell));
        }
        visitChildren(tableCell);
    }

    private String getTextContent(Node node) {
        StringBuilder sb = new StringBuilder();
        Node child = node.getFirstChild();
        while (child != null) {
            if (child instanceof Text) {
                sb.append(((Text) child).getLiteral());
            }
            child = child.getNext();
        }
        return sb.toString().trim();
    }

    public List<String> getTableHeaders() {
        return headers;
    }

    public List<List<String>> getTableRows() {
        return rows;
    }
}


测试用例


    public static void main(String[] args) {

        String content = """
                | 姓名       | 性别   | 班级        | 年龄          |
                |--------------|------|--------------------|--------------------|
                | 张三       |  男    |   兴趣一班                 |             17       |
                | 李四         | 男 | 兴趣一班  | 16  |
                """;

        List<Extension> extensions = Arrays.asList(TablesExtension.create());
        Parser parser = Parser.builder().extensions(extensions).build();

        Node document = parser.parse(content);
        TableVisitor visitor = new TableVisitor();
        document.accept(visitor);

        List<String> tableHeaders = visitor.getTableHeaders();
        List<List<String>> tableRows = visitor.getTableRows();

        System.out.println("表头: " + tableHeaders);
        System.out.println("表格行数据: "+ tableRows);

    }


总结

由于没有在commonmark中找到我们需要的vistor,所以自定义了vistor。希望可以对其他同学有所帮助吧。

### 将 Java 中的 `List` 转换为 Markdown 表格或列表 在 Java 中,可以通过遍历 `List` 并构建相应的字符串来实现将其转换为 Markdown 格式的表格或列表。以下是两种常见的方式: #### 1. **将 `List<String>` 转换为 Markdown 列表** 对于简单的 Markdown 列表,可以直接通过迭代 `List` 来生成带有序号或无序标记的内容。 ```java import java.util.Arrays; import java.util.List; public class ListToMarkdown { public static void main(String[] args) { List<String> items = Arrays.asList("元素1", "元素2", "元素3"); StringBuilder markdownUnorderedList = new StringBuilder(); StringBuilder markdownOrderedList = new StringBuilder(); for (int i = 0; i < items.size(); i++) { markdownUnorderedList.append("- ").append(items.get(i)).append("\n"); markdownOrderedList.append((i + 1)).append(". ").append(items.get(i)).append("\n"); } System.out.println(markdownUnorderedList.toString()); // 输出无序列表 System.out.println(markdownOrderedList.toString()); // 输出有序列表 } } ``` 上述代码会生成以下 Markdown 内容: - 元素1 - 元素2 - 元素3 或者: 1. 元素1 2. 元素2 3. 元素3 此方法适用于简单类型的 `List` 数据结构[^1]。 --- #### 2. **将复杂对象的 `List` 转换为 Markdown 表格** 如果 `List` 存储的是复杂的对象(如自定义类),则可以将其属性提取并格式化为 Markdown 表格形式。 假设有一个品牌列表 `List<Brand>`,其中每个品牌的字段包括名称 (`name`) 和状态 (`status`)。 ```java import java.util.Arrays; import java.util.List; class Brand { private String name; private int status; public Brand(String name, int status) { this.name = name; this.status = status; } public String getName() { return name; } public int getStatus() { return status; } } public class ListToMarkdownTable { public static void main(String[] args) { List<Brand> brands = Arrays.asList( new Brand("华为", 1), new Brand("小米", 0) ); StringBuilder tableHeader = new StringBuilder("| 品牌名 | 状态 |\n| --- | --- |\n"); StringBuilder tableBody = new StringBuilder(); for (Brand brand : brands) { tableBody.append("| ") .append(brand.getName()) .append(" | ") .append(brand.getStatus() == 1 ? "启用" : "禁用") .append(" |\n"); } System.out.println(tableHeader.toString() + tableBody.toString()); } } ``` 运行以上代码后,将会得到如下 Markdown 表格内容: | 品牌名 | 状态 | | --- | --- | | 华为 | 启用 | | 小米 | 禁用 | 这种做法适合处理更复杂的业务逻辑以及多列的数据展示需求[^2]。 --- #### 总结 无论是简单的字符串列表还是复杂的对象列表,都可以通过适当的设计和编码技巧轻松地转化为 Markdown 格式。具体实现取决于实际的需求场景以及输入数据的形式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值