Home > Back-end >  Proccessing hashtable values correctly inside a ForEach-Object
Proccessing hashtable values correctly inside a ForEach-Object

Time:12-18

I have a .xml file that I want to use to create windows .url files out of:

<?xml version="1.0" encoding="UTF-16" ?>
<items_list>
<item>
<title>About topics - PowerShell | Microsoft Learn</title>
<url>https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about?view=powershell-7.3</url>
</item>
<item>
<title>PowerShell HashTable - Everything you need to know — LazyAdmin</title>
<url>https://lazyadmin.nl/powershell/powershell-hashtable/</url>
</item>
<item>
<title>How a Regex Engine Works Internally</title>
<url>https://www.regular-expressions.info/engine.html</url>
</item>
</items_list>

I placed the Titles and URLs into a Hashtable:

$InXML = [XML](Get-Content .\test.xml)
$BookMarks = [ordered]@{
Title = (Select-Xml -xml $InXML -XPath "//title" | % {$_.Node.InnerXml}) -replace '\?|\\|/|:'
URL   = Select-Xml -xml $InXML -XPath "//url" | % {$_.Node.InnerXml}
}

Everything good so far, then I start running into problems when I try to loop through the Titles and URLs:

$wshshell = New-Object -ComObject WScript.Shell
$BookMarks | ForEach-Object {
    $Title = $_.Title
    $Url = $_.Url
    Write-Output $shortcutFilePath
    # $shortcutFilePath = Join-Path -path "c:\temp" -ChildPath "$Title.Url"
    # $shortcut = $shell.CreateShortcut($shortcutFilePath)
    # $shortcut.TargetPath = "$Url"
    # $shortcut.Save()
    
}

I commented out my actuall code in the Loop to see whats actually happening with Write-Output. All the key values get concatenated into one long title or one long .url

What I am expecting is to get a single pair of a Url and Title at a time, so that I can create the .url file in the loop.

Reading the documentations and articles on how to do this. I tried variations of:

$BookMarks.Values | ForEach-Object {
    $Title = $_.Title
    $Url = $_.Url
  Write-Output $Title
  Write-Output $Url
  }

I keep getting null variables. Any help or ideas would be really appreciated.

CodePudding user response:

I suggest simplifying and streamlining your code as follows, which bypasses your problem:

[xml] $inXML = Get-Content -Raw .\test.xml

$inXml.items_list.item | ForEach-Object {
  $title = $_.Title
  $url = $_.Url
  "[$title] [$url]" # sample output.
  # ... work with $title and $url here
  # $wshshell = New-Object -ComObject WScript.Shell
  # ...
}

The above uses PowerShell's adaptation of the XML DOM, which allows you to access elements and attributes as if they were properties.

  • Related