Search and Replace XML attribute using file name a

2019-08-05 20:16发布

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

2条回答
放我归山
2楼-- · 2019-08-05 20:31

The basic problem is that you are referring to a for variable, namely %%P, outside of the loop scope, which I do not recommend.

With pure batch scripting, I would change your code to this:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "SEARCH=00000000-0000-0000-0000-000000000000"
for %%P in ("*.xml") do (
    for /F "delims=" %%I in ('
        findstr /N /R "^" "%%~P" ^& ^> "%%~fP" break
    ') do (
        set "LINE=%%I"
        setlocal EnableDelayedExpansion
        set "LINE=!LINE:*:=!"
        if defined LINE set "LINE=!LINE:%SEARCH%=%%~nP!"
        >> "%%~fP" echo(!LINE!
        endlocal
    )
)
endlocal
exit /B

This is capable of modifying the enumerated *.xml files in the current directory directly, so no interim file is required to do the replacement of the attribute parentid.

Each file is read by findstr which precedes every line with a line number and a colon temporarily in order not to lose empty lines (remember that for /F ignores such). The command line set "LINE=!LINE:*:=!" removes the prefix afterwards. Note that delayed expansion is toggled in the for /F in order not to lose any exclamation marks occurring within the files. These measures ensure that the original *.xml file contents are not altered, except the replaced portion of course.

查看更多
倾城 Initia
3楼-- · 2019-08-05 20:35

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
    }
查看更多
登录 后发表回答