JazzyJ
JazzyJ

Reputation: 341

Change XML tags within PowerShell and keep content.

I have exported data from an EventLog using PowerShell and have created a sample Schema to import the data into SQL however there is an issue of the way the data is exported from PowerShell using ConvertToXML.

The exports of the XML looks like this;

<Property Name="Version">0</Property>

<Property Name="Qualifiers" />

<Property Name="Level">0</Property>

<Property Name="Task">14339</Property>

<Property Name="Opcode">0</Property>

<Property Name="Keywords">-9218868437227405312</Property>

<Property Name="RecordId">57963203</Property>

<Property Name="ProviderName">Microsoft-Windows-Security-Auditing</Property>

But it should look something like this;

<Version>0</Version>

<Qualifiers> />

<Level>0</Level>

<Task>14339</Task>

The code below identifies the start and end of the property name version and property tag and attempts to change it to but unfortunately it changes it without keeping the contents within the tag. I can't seem to kept the value.

$EventLog = (Get-WinEvent -ComputerName xxxxxxx-FilterXML $Query) | ConvertTo-Xml -NoTypeInformation

$EventLogModify = (Get-Content P:\EventTracking\Events.xml) | foreach{$_ -replace '(<Property Name=""Version"">(.*?)</Property>)', "<Version></Version>" };Set-Content P:\EventTracking\Events.xml $EventLogModify;

Upvotes: 2

Views: 2377

Answers (2)

walid2mi
walid2mi

Reputation: 2888

another simple way:

[Xml]$xml=@'
<root>
<Property Name="Version">0</Property>
<Property Name="Qualifiers" />
<Property Name="Level">0</Property>
<Property Name="Task">14339</Property>
<Property Name="Opcode">0</Property>
<Property Name="Keywords">-9218868437227405312</Property>
<Property Name="RecordId">57963203</Property>
<Property Name="ProviderName">Microsoft-Windows-Security-Auditing</Property>
</root>
'@



$xml.SelectNodes('//Property') | ForEach `
 -begin { 
       $h = New-Object xml
       $r = $h.CreateElement("ROOT")
       $null=$h.AppendChild($r)
   } `
 -process {
     if($_.'#text') {
         $n = $h.CreateElement($_.Name)
         $n.InnerText = $_.'#text'
         $null=$r.AppendChild($n)
     }
     else {
        $n = $h.CreateElement($_.Name)
        $null=$r.AppendChild($n)
      }
    } `
 -End {
      $h.OuterXml
      }

or:

$xml.SelectNodes('//Property')|% {
if($_.'#text') { "<{0}>{1}</{0}>" -f $_.name,$_.'#text' } else {"<$($_.name)/>"}
}

Upvotes: 0

Joey
Joey

Reputation: 354694

Your problem is in

-replace '(<Property Name=""Version"">(.*?)</Property>)', "<Version></Version>"

You replace a complete tag by an empty tag. I guess you want to use the captured group in the replacement:

-replace '(<Property Name=""Version"">(.*?)</Property>)', '<Version>$2</Version>'

Furthermore you probably used double quotes on the regex before, because there are "" in there. This likely won't match anything because it now looks for two double quotes in a row.

Another thing, you probably want to replace all at once, so use this maybe:

-replace '<Property Name="([^"]+)">([^<]+)</Property>', '<$1>$2</$1>'

That's not really enough, though:

PS> $xml -replace '<Property Name="([^"]+)">([^<]+)</Property>', '<$1>$2</$1>'
<Version>0</Version>
<Property Name="Qualifiers" />
<Level>0</Level>
<Task>14339</Task>
<Opcode>0</Opcode>
<Keywords>-9218868437227405312</Keywords>
<RecordId>57963203</RecordId>
<ProviderName>Microsoft-Windows-Security-Auditing</ProviderName>

As you can see, Qualifiers is still not changed. So another replace:

-replace '<Property Name="([^"]+)"\s*/>','<$1/>'

Looks better now

PS> $xml -replace '<Property Name="([^"]+)">([^<]+)</Property>', '<$1>$2</$1>' -replace '<Property Name="([^"]+)"\s*/>','<$1/>'
<Version>0</Version>
<Qualifiers/>
<Level>0</Level>
<Task>14339</Task>
<Opcode>0</Opcode>
<Keywords>-9218868437227405312</Keywords>
<RecordId>57963203</RecordId>
<ProviderName>Microsoft-Windows-Security-Auditing</ProviderName>

Upvotes: 3

Related Questions