Quiero agregar un prefijo de espacio de nombres a las etiquetas del espacio de nombres predeterminado de un documento XML desde el shell

Quiero agregar un prefijo de espacio de nombres a las etiquetas del espacio de nombres predeterminado de un documento XML desde el shell

Tengo un archivo SVG, que es un documento XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
  <defs
     id="defs2">
  <!-- a lot of stuff> </defs>
  <!-- more stuff-->
</svg>

Quiero agregar el prefijo svg: a todas las etiquetas correspondientes al espacio de nombres predeterminado para obtener el siguiente resultado:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg:svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
  <svg:defs
     id="defs2">
  <!-- a lot of stuff> </svg:defs>
  <!-- more stuff-->
</svg:svg>

Estoy seguro de que esto es posible en una o varias líneas de comando desde el shell usandoxmlinty/oxmlestrellapero no puedo manejarlo.

Respuesta1

Ha pasado un tiempo desde que preguntaste. Sin embargo ...

xmlstarlet editLa acción -r/ --renamerequiere un valor literal para el nuevo nombre, por lo que las funciones XPath están fuera. Sin embargo, xmlstarlet select se puede utilizar como generador de código para producir el comando de edición:

xmlstarlet select -t \
  --var sq -o "'" -b \
  -o 'xmlstarlet edit --pf \' -n \
  -m 'set:distinct(//_:*)' \
    -o '  -r ' -v 'concat($sq,"//_:",local-name(),$sq)' \
    -o '  -v ' -v 'concat($sq,"svg:",local-name(),$sq)' -o ' \' -n \
  -b \
  -f -n \
file.xml 

dónde

  • la //_:*expresión coincide con todos los nodos de elementos en el espacio de nombres predeterminado (el _acceso directo está en elxmlstarlet guía de usuario)
  • la función EXSLTset:distinct elimina duplicados
  • -ogenera una cadena literal, -nuna nueva línea, -fla ruta de entrada/URL (pero -para stdin)
  • -bfinaliza el contenedor actual ( -m, --varsin =, ao)
  • agregar una -Copción antes -tenumera el código XSLT generado

Producción:

xmlstarlet edit --pf \
  -r '//_:svg'  -v 'svg:svg' \
  -r '//_:defs'  -v 'svg:defs' \
file.xml

dónde

  • -P/ --pfconserva el formato original
  • agregar una opción -L/ --inplacedespués editadmite la edición en el lugar (no en la guía del usuario sino en xmlstarlet.txt)

Para ejecutar la salida como un script de shell:

xmlstarlet-select-command | sh -s > result.xml

En caso de que desee evitar EXSLT, -m '//_:*' --sort 'A:T:-' . canalice la salida a través de uniq, o simplemente -m '//_:*'con posibles duplicados.

Respuesta2

Usar xmlstarletde una manera particularmente brutal (espero el xpath adecuado)

for x in $(xmlstarlet sel -t -m "//*" -n -v "name()" file1.xml | sort | uniq); do 
    xmlstarlet ed -r "//svg:$x" -v "svg:$x" file1.xml > tmp.xml;
    mv tmp.xml file1.xml;
done

Como ya ha declarado el espacio de nombres svg, debe invocarlo para xpathcambiar el valor literal de los nombres de los nodos.

información relacionada