Below is an example of how to extract attributes from a xmlelement into a hashtable and then join two hashtables into one. I couldn't find a method for extracting elements on the web, folks usually goes with subnodes instead of attributes. I'm partial to attributes and had to get creative, but the solution was quite simple. The Attributes from the element only show the actual elements from the xmlfile. Its not obvious when browsing the object that -name property can be lifted, but here it's used for creating a new hashtable-row
Samplescript for proof of concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ScriptPath = $(split-path -Parent $myinvocation.MyCommand.Definition) | |
Import-Module "$($ScriptPath)\Tools.psm1" -force | |
[xml]$xml = get-content -path "$($scriptPath)\websiteNodes.xml" | |
$nodes = $xml.SelectNodes("//webSites/webSite") | |
$collection = @() | |
foreach ($node in $nodes) { | |
$propertyDefault = @{url="test";name="test2";else="else"} | |
$propertyTemp = convert-xmlAttribToHash -xmlElement $node | |
$newProperty = Join-Hashtable -master $propertyTemp -child $propertyDefault | |
$object = new-object PSObject -Property $newProperty | |
$collection += $object | |
} | |
$collection[0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function Join-Hashtable { | |
[cmdletbinding()] | |
Param ( | |
[hashtable]$Master, | |
[hashtable]$Child | |
) | |
#create clones of hashtables so originals are not modified | |
$Primary = $master.Clone() | |
$Secondary = $child.Clone() | |
#check for any duplicate keys | |
$duplicates = $Primary.keys | where {$Secondary.ContainsKey($_)} | |
if ($duplicates) { | |
foreach ($item in $duplicates) { | |
$Secondary.Remove($item) | |
} | |
} | |
#join the two hash tables | |
$result = $Primary+$Secondary | |
return $result | |
} #end Join-Hashtable | |
function convert-xmlAttribToHash { | |
param( | |
$xmlElement | |
) | |
$hashTable = @{} | |
foreach ($attrib in $xmlElement.Attributes) { | |
$hashTable.$($attrib.name) = $attrib.value | |
} | |
return $hashTable | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<webSites rootUrl="https://portal.mycompany.com/subsites/mastersite" defaultLanguage="1053" useParentTopNav="true" defaultTemplate="STS#0"> | |
<webSite name="MerSupport" url="/support/mersupport" language="1033" /> | |
<webSite name="Support" url="/support" language="1033" /> | |
<webSite name="Support3" url="/support3" /> | |
</webSites> |
This eventually led to createwebsFromStructure.ps1 that uses powershell splatting to build commands with the resulting hashtable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-PSSnapin microsoft.sharepoint.powershell | |
$scriptPath = $(split-path -Parent $MyInvocation.MyCommand.Definition) | |
Import-Module "$($scriptPath)\Tools.psm1" | |
$xmlStructureName = "webSiteNodes.xml" | |
$xmlStructurePath = Join-Path -Path $scriptPath -ChildPath $xmlStructureName | |
[xml]$xmlStructure = Get-Content -Path $xmlStructurePath | |
$root = $xmlStructure.SelectSingleNode("//webSites") | |
$rootUrl = $xmlStructure.webSites.rootUrl | |
$allWebSites = $xmlStructure.SelectNodes("//webSites/webSite") | |
#sort for order of handling first | |
foreach ($allWebSite in $allWebSites) { | |
$depth = $($allWebSite.url.Split("/").count)-1 | |
$allWebSite |Add-Member -MemberType NoteProperty "UrlDepth" -Value $depth -Force | |
} | |
$rootProperty = @{language=$root.defaultLanguage;useParentTopNav=$root.useParentTopNav;Template=$root.defaultTemplate} | |
#create websites | |
foreach ($website in ($allWebSites|sort-object urldepth)) { | |
$fullUrl = "$($rootUrl)$($website.url)" | |
$checkExists = get-spweb $fullUrl -ErrorAction SilentlyContinue | |
if ($checkExists -eq $null) { | |
write-output "Creating site at $fullUrl" | |
#join parameters with defaults | |
$propertyTemp = @{} | |
foreach ($attrib in $website.Attributes) { | |
$propertyTemp.$($attrib.name) = $attrib.value | |
} | |
$propertyTemp.url = $propertyTemp.url.Insert(0,$rootUrl) | |
$newProperty = Join-Hashtable -master $propertyTemp -Child $rootProperty | |
if ($newProperty.useParentTopNav -eq 'true') { | |
write-output "Using topparentnav" | |
$newProperty.remove('UseParentTopNav') | |
New-SPWeb @newProperty -UseParentTopNav | |
} | |
else { | |
write-output "Not using topparentNav" | |
$newProperty.remove('UseParentTopNav') | |
New-SPWeb @newProperty | |
} | |
} | |
else { write-output "Site already exists. Skipping creation..." } | |
} |
References:
https://powershell.org/2013/01/23/join-powershell-hash-tables/ - source for join-hashtable function
https://technet.microsoft.com/en-us/library/gg675931.aspx - source for details on splatting
No comments:
Post a Comment