Wendigo
Wendigo

Reputation: 73

How to embed a foreach loop in HTML in PowerShell

I am trying to create a loop in HTML in PowerShell ISE, like this:

{foreach $obj in $objects}
   <h1>$obj.Name<h1>
{/foreach}

But it only prints the last one in the list of objects. What do?

Upvotes: 1

Views: 231

Answers (1)

mklement0
mklement0

Reputation: 437428

Use an expandable (interpolating) here-string and embed a foreach statement via $(...), the subexpression operator:

# Sample objects.
$objects = [pscustomobject] @{ name = 'foo1' },
           [pscustomobject] @{ name = 'foo2' }

# Use an expandable (double-quoted) here-string to construct the HTML.
# The embedded $(...) subexpressions are *instantly* expanded.
@"
<html>
$(
  $(
    foreach ($obj in $objects) {
      "  <h1>$($obj.Name)<h1>"
    }
  ) -join "`n"
)
</html>
"@

Output:

<html>
  <h1>foo1<h1>
  <h1>foo2<h1>
</html>

If you want to define the above strings as a template, so you can perform expansion (string interpolation) repeatedly, on demand, use a verbatim here-string, and expand on demand - based on the then-current variable values via $ExecutionContext.InvokeCommand.ExpandString():

# Use a verbatim (single-quoted) here-string as a *template*:
# Note the @' / @' instead of @" / @"
$template = @'
<html>
$(
  $(
    foreach ($obj in $objects) {
      "  <h1>$($obj.Name)<h1>"
    }
  ) -join "`n"
)
</html>
'@

# Sample objects.
$objects = [pscustomobject] @{ name = 'foo1' },
           [pscustomobject] @{ name = 'foo2' }


# Expand the template now.
$ExecutionContext.InvokeCommand.ExpandString($template)

'---'

# Define different sample objects.
$objects = [pscustomobject] @{ name = 'bar1' },
           [pscustomobject] @{ name = 'bar2' }

 
# Expand the template again, using the new $objects objects.
$ExecutionContext.InvokeCommand.ExpandString($template)

Output:

<html>
  <h1>foo1<h1>
  <h1>foo2<h1>
</html>
---
<html>
  <h1>bar1<h1>
  <h1>bar2<h1>
</html>

Note:

  • Given that $ExecutionContext.InvokeCommand.ExpandString() is a bit obscure, it would be nice to have a cmdlet that provides the same functionality, named, say, Expand-String or Expand-Template, as proposed in GitHub issue #11693.

Upvotes: 1

Related Questions