Reputation: 89
I'm interested in using the ConvertFrom-Markdown cmdlet to parse values in a markdown table. The cmdlet uses the markdig markdown processor, which has an Abstract Syntax Tree that should be able to be traversed for this purpose.
How can we search/enumerate the Tokens in the following powershell snippet to return the rows and columns?
(@'
# header1
## header2
| Column1 | Column2 |
| ------- | ------- |
| Row1Column1 | Row1Column2 |
| Row2Column1 | Ro2Column2 |
'@ | ConvertFrom-Markdown).Tokens
The values that I see in the Tokens look promising, I can see Markdig.Extensions.Tables.TableCell
in the Parent
fields, but that's about as far as I can get.
Upvotes: 1
Views: 1097
Reputation: 61083
They have a MarkdownObjectExtensions.Descendants
extension method that can be used to filter, unfortunately extension methods don't translate nicely to PowerShell. This is how you could convert that Markdown table to an array of PowerShell objects using this method:
using namespace Markdig.Syntax
using namespace Markdig.Extensions.Tables
$md = @'
# header1
## header2
| Column1 | Column2 |
| ------- | ------- |
| Row1Column1 | Row1Column2 |
| Row2Column1 | Ro2Column2 |
'@ | ConvertFrom-Markdown
foreach ($table in [MarkdownObjectExtensions]::Descendants[Table]($md.Tokens)) {
foreach ($row in [MarkdownObjectExtensions]::Descendants[TableRow]($table)) {
if ($row.IsHeader) {
$headers = foreach ($header in [MarkdownObjectExtensions]::Descendants[TableCell]($row)) {
$header.Inline.Content.ToString()
}
continue
}
$tmp = [ordered]@{}; $idx = 0
foreach ($cell in [MarkdownObjectExtensions]::Descendants[TableCell]($row)) {
$tmp[$headers[$idx++]] = $cell.Inline.Content.ToString()
}
[pscustomobject] $tmp
}
}
It would result in:
Column1 Column2
------- -------
Row1Column1 Row1Column2
Row2Column1 Ro2Column2
Upvotes: 0
Reputation: 1800
If you like to import the markdown tables into PowerShell arrays, you can parse and build PsCustomObjects as well along the way...
$MarkDown = @"
# header1
## header2
| Column1 | Column2 |
| ------- | ------- |
| Row1Column1 | Row1Column2 |
| Row2Column1 | Ro2Column2 |
| Table2 Column1 |
| ------------- |
| T2 Row1 |
| T2 Row2 |
| T2 Row3 |
"@ | ConvertFrom-Markdown
$mdDoc = $Markdown.Tokens
[array]$tables = $null
$mdTables = @($mdDoc | where {$_ -is [Markdig.Extensions.Tables.Table]})
foreach ($mdTable in $mdTables) {
[array]$table = $null
$mdRows = @($mdTable | where {$_ -is [Markdig.Extensions.Tables.TableRow]})
foreach ($mdRow in $mdRows) {
$mdCells = @($mdRow | where-object { $_ -is [Markdig.Extensions.Tables.TableCell]})
$mdCellsValues = @($mdCells.Inline.Content | foreach {$_.ToString()})
if ($mdRow.IsHeader) {# don't use headers as values
$CustomProperties = $mdCellsValues
} else {# iterate throw the customobject and populate it
$thisrow = New-Object PSCustomObject | select $CustomProperties
foreach ($i in 0..($CustomProperties.Count -1)) {
$thisrow.($CustomProperties[$i]) = $mdCellsValues[$i]
}
$table += $thisrow
}# endif
}#end tablerows
$tables += ,$table #add each table a sub arrays
}#end tables
$tables
The result is available in two sub arrays
C:\> $tables[0]
Column1 Column2
------- -------
Row1Column1 Row1Column2
Row2Column1 Ro2Column2
C:\> $tables[1]
Table2 Column1
-------------
T2 Row1
T2 Row2
T2 Row3
Upvotes: 0
Reputation: 10095
Here's a way to do it.
Note I'm not sure if, example a Table
can contain only TableRow
s, so the | where-object { ... }
might not be necessary.
# set up some sample data
$md = @"
# header1
## header2
| Column1 | Column2 |
| ------- | ------- |
| Row1Column1 | Row1Column2 |
| Row2Column1 | Ro2Column2 |
"@ | ConvertFrom-Markdown
# walk the syntax tree
$mdDoc = $md.Tokens;
$mdTables = @( $mdDoc | where-object { $_ -is [Markdig.Extensions.Tables.Table] } );
foreach( $mdTable in $mdTables )
{
write-host "table";
$mdRows = @( $mdTable | where-object { $_ -is [Markdig.Extensions.Tables.TableRow] } );
foreach( $mdRow in $mdRows )
{
write-host " row";
write-host " header = $($mdRow.IsHeader)";
$mdCells = @( $mdRow | where-object { $_ -is [Markdig.Extensions.Tables.TableCell] } );
foreach( $mdCell in $mdCells )
{
write-host " cell";
$mdInline = $mdCell.Inline;
write-host " inline - $($mdInline.Content)";
}
}
}
Which gives the following output:
table
row
header = True
cell
inline - Column1
cell
inline - Column2
row
header = False
cell
inline - Row1Column1
cell
inline - Row1Column2
row
header = False
cell
inline - Row2Column1
cell
inline - Ro2Column2
Hopefully that'll be enough to get you started...
Upvotes: 3