生成Markdown表?

时间:2012-11-15 08:56:22

标签: markdown pandoc

有没有办法从对象生成表(Python / Ruby / Java / C#)?

我想以编程方式创建一个简单的表。我有一些对象,我想将一些属性映射到标题,将集合映射到行。

为何选择Markdown?因为我想稍后手动编辑该文档。现在,整个过程看起来像这样:

  • 报告引擎位于C#
  • 有生成DOCX的对象(有中间XML或类似的东西)
  • 几乎总是我必须做一些小修补,我必须在MS Word中打开docx文档
  • 要求开发人员团队修复每一个错误都很麻烦,因为他们没有时间立即执行此操作,我必须等待下一个版本。

我已经想出如果我得到Markdown文档,我可以轻松编辑它,插入一些变量并使用pandoc用给定数据替换这些变量。但要获得Markdown,我必须知道开发人员如何在Markdown中生成表格。

3 个答案:

答案 0 :(得分:6)

我需要做同样的事情来生成Doxygen Markdown表,所以我想我会分享。我已经在Python 2.7和3.3中成功运行了示例代码,尽管我不能声称我已经严格测试过它。

# Generates tables for Doxygen flavored Markdown.  See the Doxygen
# documentation for details:
#   http://www.doxygen.nl/manual/markdown.html#md_tables

# Translation dictionaries for table alignment
left_rule = {'<': ':', '^': ':', '>': '-'}
right_rule = {'<': '-', '^': ':', '>': ':'}

def evalute_field(record, field_spec):
    """
    Evalute a field of a record using the type of the field_spec as a guide.
    """
    if type(field_spec) is int:
        return str(record[field_spec])
    elif type(field_spec) is str:
        return str(getattr(record, field_spec))
    else:
        return str(field_spec(record))

def table(file, records, fields, headings, alignment = None):
    """
    Generate a Doxygen-flavor Markdown table from records.

    file -- Any object with a 'write' method that takes a single string
        parameter.
    records -- Iterable.  Rows will be generated from this.
    fields -- List of fields for each row.  Each entry may be an integer,
        string or a function.  If the entry is an integer, it is assumed to be
        an index of each record.  If the entry is a string, it is assumed to be
        a field of each record.  If the entry is a function, it is called with
        the record and its return value is taken as the value of the field.
    headings -- List of column headings.
    alignment - List of pairs alignment characters.  The first of the pair
        specifies the alignment of the header, (Doxygen won't respect this, but
        it might look good, the second specifies the alignment of the cells in
        the column.

        Possible alignment characters are:
            '<' = Left align (default for cells)
            '>' = Right align
            '^' = Center (default for column headings)
    """

    num_columns = len(fields)
    assert len(headings) == num_columns

    # Compute the table cell data
    columns = [[] for i in range(num_columns)]
    for record in records:
        for i, field in enumerate(fields):
            columns[i].append(evalute_field(record, field))

    # Fill out any missing alignment characters.
    extended_align = alignment if alignment != None else []
    if len(extended_align) > num_columns:
        extended_align = extended_align[0:num_columns]
    elif len(extended_align) < num_columns:
        extended_align += [('^', '<')
                           for i in range[num_columns-len(extended_align)]]

    heading_align, cell_align = [x for x in zip(*extended_align)]

    field_widths = [len(max(column, key=len)) if len(column) > 0 else 0
                    for column in columns]
    heading_widths = [max(len(head), 2) for head in headings]
    column_widths = [max(x) for x in zip(field_widths, heading_widths)]

    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(heading_align, column_widths)])
    heading_template = '| ' + _ + ' |'
    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(cell_align, column_widths)])
    row_template = '| ' + _ + ' |'

    _ = ' | '.join([left_rule[a] + '-'*(w-2) + right_rule[a]
                    for a, w in zip(cell_align, column_widths)])
    ruling = '| ' + _ + ' |'

    file.write(heading_template.format(*headings).rstrip() + '\n')
    file.write(ruling.rstrip() + '\n')
    for row in zip(*columns):
        file.write(row_template.format(*row).rstrip() + '\n')

这是一个简单的测试用例:

import sys

sys.stdout.write('State Capitals (source: Wikipedia)\n\n')

headings = ['State', 'Abrev.', 'Capital', 'Capital since', 'Population',
            'Largest Population?']

data = [('Alabama', 'AL', '1819', 'Montgomery', '1846', 155.4, False,
         205764),
        ('Alaska', 'AK', '1959', 'Juneau', '1906', 2716.7, False, 31275),
        ('Arizona', 'AZ', '1912', 'Phoenix', '1889',474.9, True, 1445632),
        ('Arkansas', 'AR', '1836', 'Little Rock', '1821', 116.2, True,
         193524)]

fields = [0, 1, 3, 4, 7, lambda rec: 'Yes' if rec[6] else 'No']

align = [('^', '<'), ('^', '^'), ('^', '<'), ('^', '^'), ('^', '>'),
         ('^','^')]

table(sys.stdout, data, fields, headings, align)

给出这个输出:

State Capitals (source: Wikipedia)

|  State   | Abrev. |   Capital   | Capital since | Population | Largest Population? |
| :------- | :----: | :---------- | :-----------: | ---------: | :-----------------: |
| Alabama  |   AL   | Montgomery  |     1846      |     205764 |         No          |
| Alaska   |   AK   | Juneau      |     1906      |      31275 |         No          |
| Arizona  |   AZ   | Phoenix     |     1889      |    1445632 |         Yes         |
| Arkansas |   AR   | Little Rock |     1821      |     193524 |         Yes         |

Doxygen将其渲染为:

Sample

答案 1 :(得分:1)

我需要以编程方式为recent project生成Markdown,因此我构建了一个库并将其发布到GitHub上。希望你会发现它很有用。

该项目名为MarkdownLog,它是一个轻量级(即最小依赖项),可移植的.NET库(PCL),可以从.NET数据结构(如集合和词典)生成Markdown。我将它用于记录内部程序数据结构以用于诊断目的,但它也应该满足您的需求。

以下是从集合构建Markdown表的方法:

var data = new[]
{
    new{Year = 1991, Album = "Out of Time", Songs=11, Rating = "* * * *"},
    new{Year = 1992, Album = "Automatic for the People", Songs=12, Rating = "* * * * *"},
    new{Year = 1994, Album = "Monster", Songs=12, Rating = "* * *"}
};

Console.Write(data.ToMarkdownTable());

// Produces:
//
//     Year | Album                    | Songs | Rating   
//     ----:| ------------------------ | -----:| --------- 
//     1991 | Out of Time              |    11 | * * * *  
//     1992 | Automatic for the People |    12 | * * * * *
//     1994 | Monster                  |    12 | * * *    

请注意,当使用GitHub风格的Markdown解析器解析此输出时,它将生成一个HTML表。

默认情况下,列根据其数据类型对齐(数字右对齐,字符串左对齐),标题名称根据对象的属性名称生成。如果这不是您想要的,那么有许多覆盖可以让您更好地控制输出。

内置支持所有standard Markdown elementsGFM tables。我还添加了一些我需要的额外元素类型(条形图,iOS UITableView),它们实现为code blocks,因此它们仍然符合Markdown标准。

我最近才将代码上传到GitHub,因此文档目前是基本的。话虽如此,项目中有大量的单元测试,应该证明它是如何工作的。

我很感激这个问题已经有一段时间了,但我希望这个项目对某些人有用。

答案 2 :(得分:0)

使用 Apache Freemarker 通过 Java 代码呈现 HTML,然后将其转换为 Markdown。这是将 HTML 表格转换为 Markdown 的方法。

Flexmark-java to convert HTML table to Markdown