Recently I started to look into some more detail at PowerShell and the SharePoint 2010 Snap-in. As a small exercise I wanted to create something (somewhat) usefull. I came up with a small site structure install script for SP2010. First the source configuration, an xml, with the sites and subsites I wanted to created:
<?xml version="1.0" ?>
<site title="Test Portal" template="STS#0" lcid="1033" owner="sp2010\administrator">
<features>
<feature id="{22a9ef51-737b-4ff2-9346-694633fe4416}"/>
<feature id="{f6924d36-2fa8-4f0b-b16d-06b7250180fa}"/>
<feature id="{94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb}"/>
</features>
<webs>
  <web url="Subsite1" title="Subsite 1" template="STS#0" lcid="1033" />
  <web url="Subsite2" title="Subsite 2" template="STS#0" lcid="1033">
   <webs>
    <web url="SubSubsite1" title="SubSubsite 1" template="STS#0" lcid="1033" />
    <web url="SubSubsite2" title="SubSubsite 2" template="STS#0" lcid="1033" />
   </webs>
  </web>
  <web url="Subsite3" title="Subsite 3" template="STS#0" lcid="1033">
   <webs>
    <web url="SubSubsite1" title="SubSubsite 1" template="STS#0" lcid="1033" />
    <web url="SubSubsite2" title="SubSubsite 2" template="STS#0" lcid="1033" />
   </webs>
  </web>
</webs>
</site>

Next I wrote two helper function inside my PowerShell script:
function ActivateFeatures([System.Xml.XmlNode]$node){
#features for current web
$features = $node.selectnodes("./features/feature") # XPath is case sensitive
foreach ($feature in $features) {
$fid= $feature.getAttribute("id")
write-host -f blue "Activating Feature $fid at $baseurl"
Enable-SPFeature -Identity "$fid" -Url $baseurl -Force
}
}

function ParseNode([System.Xml.XmlNode]$node){
$url = $node.getAttribute("url")
$title = $node.getAttribute("title")
$lcid = $node.getAttribute("lcid")
$template = $node.getAttribute("template")
$baseurl = "$baseurl$url"

write-host -f red "Going to create site at: $baseurl with Title: $title"
New-SPWeb -Url "$baseurl" -Name $title -Template $template -Language $lcid

ActivateFeatures($node);

# add a trailing slash to create urls
$baseurl = "$baseurl/"

# sub webs
$subnodes = $node.selectnodes("./webs/web") # XPath is case sensitive
foreach ($subnode in $subnodes) {
ParseNode($subnode)
}
}

First remove the existing site collection:
$baseurl ="http://portal.sp2010.com"
Write-Host -f Red "Removing Site Collection at $baseurl"
Remove-SPSite $baseurl

And then start reading the xml file and start creating a site collection
write-host -f green "Opening sites.xml"

[System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
$file = resolve-path("./sites.xml")

$xd.Load($file)

#site collection
$sitenode = $xd.selectsinglenode("/site") # XPath is case sensitive
$title = $sitenode.getAttribute("title")
$lcid = $sitenode.getAttribute("lcid")
$template = $sitenode.getAttribute("template")
$owner = $sitenode.getAttribute("owner")

write-host -f red "Creating Site Collection at $baseurl"
New-SPSite -Url "$baseurl" -Name $title -Template $template -Language $lcid -OwnerAlias $owner
ActivateFeatures($sitenode);

# add a trailing slash to create urls
$baseurl = "$baseurl/"

# subwebs
$nodelist = $xd.selectnodes("/site/webs/web") # XPath is case sensitive
foreach ($node in $nodelist) {
ParseNode($node)
}

write-host "End of sites.xml"

And add this to the top of your SP2010 PowerShell Script to always load the Snap-in.
$snapin="Microsoft.SharePoint.PowerShell"
if (get-pssnapin $snapin -ea "silentlycontinue") {
write-host -f Green "PSsnapin $snapin is loaded"
}
elseif (get-pssnapin $snapin -registered -ea "silentlycontinue") {
write-host -f Green "PSsnapin $snapin is registered"
Add-PSSnapin $snapin
write-host -f Green "PSsnapin $snapin is loaded"
}
else {
write-host -f orange "PSSnapin $snapin not found" -foregroundcolor Red
}

You can download both files here: codeplex.com