Piotr Jurski Piotr Jurski - 3 months ago 48
PowerShell Question

Search and Replace XML attribute using file name as the attribute value (Powershell or Batch File)

I need help to find and replace an attribute "parentid" that has "00000000-0000-0000-0000-000000000000" in each XML file in a folder. The actual filename of each file without the extension should replace the "parentid" attribute in XML. (Powershell or Batch file)

For example: C:\Folder\


4de6d1b4-b014-4cb3-bb61-649737a8217b.xml

4d2345b4-b415-5656-12dv-832jnm89234n.xml

...

Content of the XML:

<comment id="4de6d1b4-b014-4cb3-bb61-649737a8217b" parentid="00000000-0000-0000-0000-000000000000" approved="True">
<date>2014-12-20 22:23:40</date>
<author>Joe Doe</author>
<email>test@example.com</email>
<country />
<ip>0.0.0.0</ip>
<avatar />
<content>Test</content>
</comment>


I appreciate everyone's help!

This is what I have so far however it replaces the whole line not the actual value of the attribute.

@echo off &setlocal
setlocal enabledelayedexpansion

set "search=00000000-0000-0000-0000-000000000000"
set "replace=%%~nP"
set "textfile=%%~nxP"
set "newfile=%%~nP"
for /r %%P in (*) do (
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
set "line=!line:%search%=%replace%!"
echo(!line!))>"%newfile%"
)
)
endlocal


@ECHO ON

Answer

There are lots of examples of loading/parsing an XML file in PowerShell, but the fastest solution in such a simple case as this one would be to use a plain text search/replace on a string that holds the entire file:

$searchFor = 'parentid="00000000-0000-0000-0000-000000000000"'
Get-ChildItem -Literal 'c:\folder' -Filter '*.xml' -Recurse |
    Where {
        Select-String $searchFor -Path $_ -CaseSensitive -SimpleMatch
    } |
    ForEach {
        $text = [IO.File]::ReadAllText($_.FullName)
        $text.replace($searchFor, 'parentid="' + $_.BaseName + '"') |
            Out-File (Join-Path $_.Directory "$($_.BaseName)-new.xml") -Encoding utf8
    }