How to get an escaped xml attribute value in PowerShell without it being unescaped

12,521

Solution 1

Using the sample XML above, each of the following will produce the original, escaped value for the bar attribute:

Using XPath:

$val = $xml | select-xml "/foo/@bar"
$val.Node.get_innerXml()

Using PowerShell's native XML syntax:

$xml.foo.attributes.item(0).get_innerXml()

Solution 2

[Security.SecurityElement]::Escape($xml.foo.bar)

Solution 3

You can also use

[System.Web.HttpUtility]::HtmlEncode($xml.foo.bar).

There is a good answer on html encoding with PowerShell found here: What is the best way to escape html specific characters in a string in (PowerShell)

I'm not sure its any better than @shay's answer because the data is still passing through the XML parser, which returns the unescaped value, which is then passed back through a function to escape it again.

The 'content' has been manipulated in any case and its not 'the original content'. It may be splitting hairs, but in the past when I've needed non-repudiation on what was originally sent, I've stored the whole blob as a text.

It may be acceptable to grab the 'text' by accessing @bar attributes OuterXml property. That OuterXml property will return:

bar="&foobar"

From there, we can do something like:

$xml.foo.attributes['bar'].OuterXml.Split("=")[1]

Which returns:

"&foobar"

I think this is where we want to end up, but you can probably do that in a little nicer way. :)

Share:
12,521
kiprainey
Author by

kiprainey

Software consultant in Chicago, Illinois.

Updated on July 10, 2022

Comments

  • kiprainey
    kiprainey almost 2 years

    Given the following xml:

    <foo bar="&amp;foobar">some text</foo>
    

    I need to get the value of the bar attribute without it being unescaped. Every method I've tried thus far in PowerShell results in this value:

    &foobar
    

    Rather than this:

    &amp;foobar
    

    I need the latter, as I need the literal, properly escaped value to persist.

    If I do this:

    [xml]$xml = "<foo bar='&amp;foobar'>some text</foo>"
    $xml.foo.bar
    

    The attribute value is unescaped (i.e. &foobar).

    If I do this:

    $val = $xml | select-xml "/foo/@bar"
    $val.Node.Value
    

    The attribute value is unescaped (i.e. &foobar).

    What is the best way to ensure that I get the original, escaped value of an attribute with PowerShell?