¿Usar xmlstarlet para eliminar un elemento completo que coincida con un valor de atributo?

Jan 01 2021

Mi pregunta es similar a sed: eliminar el nodo XML que contiene cierto elemento: Unix y Linux Stack Exchange . Intentar implementar las sugerencias allí me ha mantenido ocupado todo el día, pero no he logrado que nada funcione, así que estoy publicando una pregunta.

Dentro de un script bash, necesito eliminar un <folder>elemento completo cuando el idatributo coincide con un valor dado. De hecho, estoy usando grupos de usuarios para hacer parte de esto. Digamos que un usuario no está en el grupo folder_a; entonces todo el <folder>elemento con atributo id=".Folder_A"debe eliminarse de config.xml. (También elimino la carpeta del disco).

Mi script de bash se ve así:

#!/bin/bash

grouplist=$(groups $theuser);
for foldername in '.Folder_A' '.Folder_B'; do
  grpnm="${foldername,,}"|sed -e 's/^.//' if ! [[ $grouplist =~ ${grpnm} ]]; then perl -0777 -pe "s|(<folder.*?</folder>)|$1=~ /id=\"$foldername\"/?"":$1|gse" config.xml > config.xml
    rm -fr "$foldername" else echo "permitting access to ${foldername}"
  fi
done

El comando de perl no funciona. Es solo una de las muchas variantes que he probado. También probé sed. Preferiría usar xmlstarlet, pero tuve aún más problemas con él.

Editar : acabo de encontrar esta respuesta:https://unix.stackexchange.com/a/339089/393289 Me ayudó a pensar en esto:

xml ed -d '//configuration/folder[contains(@id,".Folder_A")]' config.xml

Siento que estoy más cerca ahora. (Traté de votar esa respuesta, pero todavía no tengo suficiente representante). Sin embargo, todavía no puedo traducir el nombre del atributo a una variable bash debido a las comillas o algo más.

Por cierto, ¿cómo hago para realizar una edición en el lugar (similar al sed -icomando) una vez que lo hago funcionar?

Aquí hay un archivo config.xml de ejemplo:

    <?xml version="1.0"?>
    <configuration version="32">
        <folder id=".Folder_A" label=".Folder_A" path="~/Sync/.Folder_A" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
            <filesystemType>basic</filesystemType>
            <device id="123ABC" introducedBy="">
                <encryptionPassword/>
            </device>
            <device id="987ZYX" introducedBy="">
                <encryptionPassword/>
            </device>
            <minDiskFree unit="">0</minDiskFree>
            <versioning>
                    <cleanupIntervalS>0</cleanupIntervalS>
            </versioning>
            <copiers>0</copiers>
            <disableSparseFiles>false</disableSparseFiles>
            <disableTempIndexes>false</disableTempIndexes>
            <paused>false</paused>
            <weakHashThresholdPct>25</weakHashThresholdPct>
            <markerName>.stfolder</markerName>
        </folder>
        <folder id=".Folder_B" label="Corporate (.Folder_B)" path="~/Sync/.Folder_B" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="5" ignorePerms="true" autoNormalize="false">
            <filesystemType>basic</filesystemType>
            <device id="123ABC" introducedBy="">
                <encryptionPassword/>
            </device>
            <device id="987ZYX" introducedBy="">
                <encryptionPassword/>
            </device>
            <minDiskFree unit="">0</minDiskFree>
            <versioning>
                    <cleanupIntervalS>0</cleanupIntervalS>
            </versioning>
            <copiers>0</copiers>
            <disableSparseFiles>false</disableSparseFiles>
            <disableTempIndexes>false</disableTempIndexes>
            <paused>false</paused>
            <weakHashThresholdPct>25</weakHashThresholdPct>
            <markerName>.stfolder</markerName>
        </folder>
        <device id="123ABC" name="laptop" compression="always" introducer="false" skipIntroductionRemovals="false" introducedBy="">
            <paused>false</paused>
            <autoAcceptFolders>true</autoAcceptFolders>
            <maxSendKbps>0</maxSendKbps>
            <maxRecvKbps>0</maxRecvKbps>
            <maxRequestKiB>0</maxRequestKiB>
            <untrusted>false</untrusted>
        </device>
        <device id="987ZYX" name="desktop" compression="always" introducer="false" skipIntroductionRemovals="false" introducedBy="">
            <paused>false</paused>
            <autoAcceptFolders>true</autoAcceptFolders>
            <maxSendKbps>0</maxSendKbps>
            <maxRecvKbps>0</maxRecvKbps>
            <maxRequestKiB>0</maxRequestKiB>
            <untrusted>false</untrusted>
        </device>
        <gui enabled="true" tls="true" debugging="false">
            <address>127.0.0.1:8384</address>
            <apikey>98qewr0qe9r</apikey>
            <theme>default</theme>
        </gui>
        <ldap/>
        <options>
            <listenAddress></listenAddress>
            <maxSendKbps>0</maxSendKbps>
            <maxRecvKbps>0</maxRecvKbps>
            <reconnectionIntervalS>60</reconnectionIntervalS>
            <relaysEnabled>false</relaysEnabled>
            <relayReconnectIntervalM>10</relayReconnectIntervalM>
            <startBrowser>false</startBrowser>
            <urAccepted>-1</urAccepted>
            <urSeen>3</urSeen>
            <urUniqueID/>
            <urPostInsecurely>false</urPostInsecurely>
            <urInitialDelayS>1800</urInitialDelayS>
            <restartOnWakeup>true</restartOnWakeup>
            <upgradeToPreReleases>false</upgradeToPreReleases>
            <keepTemporariesH>24</keepTemporariesH>
            <cacheIgnoredFiles>false</cacheIgnoredFiles>
            <progressUpdateIntervalS>5</progressUpdateIntervalS>
            <limitBandwidthInLan>false</limitBandwidthInLan>
            <overwriteRemoteDeviceNamesOnConnect>false</overwriteRemoteDeviceNamesOnConnect>
            <tempIndexMinBlocks>10</tempIndexMinBlocks>
            <trafficClass>0</trafficClass>
            <defaultFolderPath>~/Sync/</defaultFolderPath>
            <maxFolderConcurrency>0</maxFolderConcurrency>
            <crashReportingEnabled>false</crashReportingEnabled>
            <databaseTuning>auto</databaseTuning>
            <maxConcurrentIncomingRequestKiB>0</maxConcurrentIncomingRequestKiB>
            <announceLANAddresses>false</announceLANAddresses>
            <sendFullIndexOnUpgrade>false</sendFullIndexOnUpgrade>
        </options>
    </configuration>

Este es un ejemplo de config.xml para sincronizar.

Respuestas

1 Freddy Jan 01 2021 at 10:10

Use la opción -L/ --inplace(ver xml edit --help) y la coincidencia exacta de la respuesta vinculada:

xml ed -L -d "//configuration/folder[@id=\"$foldername\"]" config.xml