Necesito ayuda para encontrar y reemplazar un atributo "parentid" que tiene "00000000-0000-0000-0000-000000000000" en cada archivo XML en una carpeta. El nombre de archivo real de cada archivo sin la extensión debe reemplazar el atributo "parentid" en XML. (Archivo Powershell o Batch)

Por ejemplo: C: \ Carpeta \

4de6d1b4-b014-4cb3-bb61-649737a8217b.xml
4d2345b4-b415-5656-12dv-832jnm89234n.xml
...

Contenido del 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>

¡Aprecio la ayuda de todos!

Esto es lo que tengo hasta ahora, sin embargo, reemplaza toda la línea, no el valor real del atributo.

@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
1
Piotr Jurski 29 ago. 2016 a las 18:31

2 respuestas

La mejor respuesta

El problema básico es que te refieres a una variable for, a saber, %%P, fuera del alcance del bucle, que no recomiendo.

Con secuencias de comandos por lotes puros, cambiaría su código a esto:

@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

Esto es capaz de modificar los archivos *.xml enumerados en el directorio actual directamente, por lo que no se requiere ningún archivo provisional para reemplazar el atributo parentid.

Cada archivo es leído por findstr que precede a cada línea con un número de línea y dos puntos temporalmente para no perder líneas vacías (recuerde que for /F las ignora). La línea de comando set "LINE=!LINE:*:=!" elimina el prefijo después. Tenga en cuenta que la expansión retardada está activada en for /F para no perder ningún signo de exclamación que se produzca dentro de los archivos. Estas medidas garantizan que el contenido del archivo *.xml original no se altere, excepto la parte reemplazada, por supuesto.

1
aschipfl 29 ago. 2016 a las 17:12

Hay muchos ejemplos de carga / análisis de un archivo XML en PowerShell, pero la solución más rápida en un caso tan simple como este sería usar una búsqueda / reemplazo de texto sin formato en una cadena que contenga todo el archivo:

$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
    }
1
wOxxOm 29 ago. 2016 a las 16:25