
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 edit
La acción -r
/ --rename
requiere 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 EXSLT
set:distinct
elimina duplicados -o
genera una cadena literal,-n
una nueva línea,-f
la ruta de entrada/URL (pero-
para stdin)-b
finaliza el contenedor actual (-m
,--var
sin=
, ao)- agregar una
-C
opción antes-t
enumera 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
/--pf
conserva el formato original- agregar una opción
-L
/--inplace
despuésedit
admite 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 xmlstarlet
de 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 xpath
cambiar el valor literal de los nombres de los nodos.