My regex works for picking up individual areas of the string content, but when I put it in the code to get the map of key-value pairs, the map is wrong. Any ideas?
The repeating content looks like this, with differing right side for alarmID like 12-5000, and the Key Name like LOAD_MEDIA:
<?xml version="1.0" encoding="utf-16"?>
<Configuration>
<Key Name="Alarms">
<Key Name="LOAD_MEDIA">
<Value Name="AlarmID">12-5000</Value>
<Value Name="blah">Dialog.Cut</Value>
<Value Name="blah1"></Value>
<Value Name="blah2">Dialog.Cancel</Value>
<Value Name="blah3">false</Value>
<Value Name="blah4">true</Value>
<Key Name="Sizes">
<Key Name="57x">
<Value Name="blah1">7</Value>
<Value Name="blah2">9</Value>
<Value Name="blah3">Dialog.57</Value>
</Key>
<Key Name="88">
<Value Name="blah1">10</Value>
<Value Name="blah2">10</Value>
<Value Name="blah3">Dialog.88</Value>
</Key>
<Key Name="810">
<Value Name="blah1">10</Value>
<Value Name="blah2">12</Value>
<Value Name="blah3">Dialog.810</Value>
</Key>
<Key Name="114">
<Value Name="blah1">1</Value>
<Value Name="blah2">1</Value>
<Value Name="blah3">Dialog.114</Value>
</Key>
<Key Name="10">
<Value Name="blah1">1</Value>
<Value Name="blah2">2</Value>
<Value Name="blah3">Dialog.10</Value>
</Key>
</Key>
</Key>
<Key Name="LOAD_MEDIA2">
<Value Name="AlarmID">12-5001</Value>
<Value Name="blah">Dialog.Cut</Value>
<Value Name="blah1"></Value>
<Value Name="blah2">Dialog.Cancel</Value>
<Value Name="blah3">false</Value>
<Value Name="blah4">true</Value>
<Key Name="Sizes">
<Key Name="57x">
<Value Name="blah1">7</Value>
<Value Name="blah2">9</Value>
<Value Name="blah3">Dialog.57</Value>
</Key>
<Key Name="88">
<Value Name="blah1">10</Value>
<Value Name="blah2">10</Value>
<Value Name="blah3">Dialog.88</Value>
</Key>
<Key Name="810">
<Value Name="blah1">10</Value>
<Value Name="blah2">12</Value>
<Value Name="blah3">Dialog.810</Value>
</Key>
<Key Name="114">
<Value Name="blah1">1</Value>
<Value Name="blah2">1</Value>
<Value Name="blah3">Dialog.114</Value>
</Key>
<Key Name="10">
<Value Name="blah1">1</Value>
<Value Name="blah2">2</Value>
<Value Name="blah3">Dialog.10</Value>
</Key>
</Key>
</Key>
</Key>
</Configuration>
..repeats format
For some reason, my errorMap returned is not even close to correct.
This is the code that is supposed to return key-value pairs in the $errorMap:
function Get-AlarmIDs{
[cmdletbinding()]
Param ([string]$fileContent)
# create an ordered hashtable to store the results
$errorMap = [ordered]@{}
# process the lines one-by-one
switch -Regex ($fileContent -split '\r?\n') {
'[\t] ?<Key Name="(.*)">[\r?\n\s] ?<Value' { #match Key Name followed by Value
if(-not($matches[1] -match '[0-9]')) #use if it's not something like 57
{
$key = ($matches[1]).Trim()
}
}
'AlarmID">(.*)<' { #match AlarmID like 12-5700
$errorMap[$key] = ($matches[1]).Trim()
}
}
return $errorMap
}
I want the map to look like this:
LOAD_MEDIA, 12-5000
LOAD_MEDIA2, 12-3
...
I know that my test on regex101.com shows that my key and value separately pick up the lines needed, but when I put it together in the code, the map is all messed up:
[ordered dictionary:1]
[0]: [6,"12-5900"]
I'm not sure where it's getting a 6 from, and the 12-5900 is about last in a repeating sequence that should have returned maybe 5 before the 12-5900.
I'm using powershell 5.1 and Visual Studio code.
Update:
I'm trying to do this the xml way, and not sure how to get out of the xml what I need.
[xml]$xmlElm = (select-xml -xpath / -path $fileNamePath).node #Get-Content $fileNamePath
$xmlElem.Configuration.'Key Name'.'Key Name'.Value #this doesn't print anything...shouldn't it?
Update2:
Trying some more...
[xml]$xmldocument = Get-Content $fileNamePath
$tmp1 = $xmldocument.ChildNodes.selectNodes("*")
$tmp2 = $xmldocument.ChildNodes.selectNodes("*/Key")
$tmp3 = $xmldocument.Key.Value.AlarmID[0] #this is indexing into null
$tmp4 = $xmldocument.Key.Value #this is null
Update3:
I'm trying what's in Santiago's answer, but get blank Value in the map.
[xml]$xmldocument = Get-Content $fileNamePath
$result = foreach($key in $xmldocument.Configuration.Key.Key)
{
[pscustomobject]@{
Key = $key.Name
Value = $key.Value.Where{$_Name -eq 'AlarmID'}.'#text'
}
}
Gives (blank values)
[0]: @{Key=LOAD_MEDIA; Value=}
[1]: @{Key=Load_MEDIA2; Value=}
I'm not sure what's different.
Update4:
$result = foreach($key in $xmldocument.Configuration.Key.Key)
{
[pscustomobject]@{
Key = $key.Name
Value = $key.Value
}
}
return $result
When I look at $result, it looks like this:
[0]: @{Key=LOAD_MEDIA; Value=System.Object[]}
[1]: @{Key=Load_MEDIA2; Value=System.Object[]}
CodePudding user response:
There is likely a better way than this but for now, this should help you get what you're looking for. Assuming you already have the XML loaded in a variable, in this case $xml
:
$result = foreach($key in $xml.Configuration.Key.Key) {
[pscustomobject]@{
Key = $key.Name
Value = $key.Value.Where{$_.Name -eq 'AlarmID'}.'#text'
}
}
$result
using the XML in question should look like this:
Key Value
--- -----
LOAD_MEDIA 12-5000
LOAD_MEDIA2 12-5001