1

I have some ps code, that downloads xml via http and check some xml in it

[xml]$stuff = $wc.DownloadString('url') 

$xmlvalue = $stuff.SelectSingleNode('xpath') 

if ($xmlvalue.'#text' -eq "value")

{
$state = 'OK'
Write-Host 'ok'    
}

All i need is an ability to run that script as

script.ps1 -url -xpath -operator -value

It`s no problem at all, except -operator

I can`t use param like -operator "-eq", because it will be an error

Any way to do it ?

Igor Kuznetsov
  • 331
  • 1
  • 5
  • 13

2 Answers2

2

You can generate scriptblock on the fly:

Param
(
    [string]$Url,

    [string]$Xpath,

    [ValidateSet('eq', 'ne', 'like')]
    [string]$Operator,

    [string]$Value
)

[xml]$stuff = $wc.DownloadString('url') 

$xmlvalue = $stuff.SelectSingleNode('xpath') 

$ScriptBlock = @'
    if($xmlvalue.'#text' -{0} "value")
    {{
        $state = 'OK'
        Write-Host 'ok'    
    }}
'@ -f $Operator

. $([scriptblock]::Create($ScriptBlock))
beatcracker
  • 5,773
  • 1
  • 15
  • 36
  • So i use if($xmlvalue.'#text' {0} '{1}') // The term 'if($xmlvalue.'#text' -eq 'OK') { $state = 'OK' } else { $state = 'ERROR' } ' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, veri fy that the path is correct and try again. Whe ps say snippet code wrong? it works without it – Igor Kuznetsov Feb 24 '16 at 13:16
  • @IgorKuznetsov See updated answer, it should work now. And you have to double `{` and `}` if you want to use them with `-f` operator, otherwise they will be treated as placeholders (`{0}`). – beatcracker Feb 24 '16 at 13:57
  • @IgorKuznetsov Well it's pretty easy, actually. You create scriptblock from string and the dot-source it, like a file. More about scriptblocks: [Some observations about Powershell script blocks](https://mjolinor.wordpress.com/2012/03/03/some-observations-about-powershell-script-blocks/), [getnewclosure() VS \[scriptblock\]::create()](https://mjolinor.wordpress.com/2011/02/13/getnewclosure-vs-scriptblockcreate/) – beatcracker Feb 24 '16 at 19:28
0

I feel like you could simplify this if you just used regex instead. Then you don't have to worry about dynamic operators. You are just doing string comparisons so you can get the equivalent of -like -match and -eq with the right pattern.

if ($xmlvalue.'#text' -match $pattern){
    $state = 'OK'
    Write-Host 'ok'    
}

I would leave the if condition just like that. The $pattern is what you would change.

  • Starts with: ^text
  • Ends with" text$
  • Is equal to: ^text$
  • String contains: text

Just need to be careful where regex metacharacters are concerned. You can always use the regex escape method so you don't have to worry about those. So a simple string contains example would be this:

$pattern = [regex]::escape("c:\temp")

Possible learning curve with regular expression but it is a powerful thing to know. Have a look at this question which covers what I am about to show you. Specifically the answer and where that covers anchors.

Reference - What does this regex mean?

Community
  • 1
  • 1
Matt
  • 40,384
  • 7
  • 62
  • 97