
Eu tenho um arquivo SVG, que é um 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>
Quero adicionar o prefixo svg: a todas as tags correspondentes ao namespace padrão para obter a próxima saída:
<?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>
Tenho certeza de que isso é possível em uma ou algumas linhas de comando do shell usandoxmllinte/ouxmlstarletmas não consigo lidar com isso.
Responder1
Já faz um tempo desde que você perguntou. No entanto ...
xmlstarlet edit
A ação -r
/ --rename
requer um valor literal para o novo nome, portanto as funções XPath estão fora. No entanto, xmlstarlet select
pode ser usado como gerador de código para produzir o comando de edição:
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
onde
- a
//_:*
expressão corresponde a todos os nós de elemento no namespace padrão (o_
atalho está noxmlstarlet
Guia do usuário) - a função EXSLT
set:distinct
elimina duplicatas -o
gera uma string literal,-n
uma nova linha,-f
o nome do caminho/URL de entrada (mas-
para stdin)-b
termina o contêiner atual (-m
,--var
sem=
, ao)- adicionar uma
-C
opção antes-t
de listar o código XSLT gerado
Saída:
xmlstarlet edit --pf \
-r '//_:svg' -v 'svg:svg' \
-r '//_:defs' -v 'svg:defs' \
file.xml
onde
-P
/--pf
preserva a formatação original- adicionar uma opção
-L
/ depois de suportar edição no local (não no guia do usuário, mas em--inplace
edit
xmlstarlet.txt)
Para executar a saída como um script de shell:
xmlstarlet-select-command | sh -s > result.xml
Caso você queira evitar EXSLT, em vez disso -m '//_:*' --sort 'A:T:-' .
, canalize a saída através de uniq
, ou simplesmente -m '//_:*'
com possíveis duplicatas.
Responder2
Usando xmlstarlet
de uma forma particularmente brutal (aguardo o xpath adequado)
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 você já declarou o namespace svg
, é necessário invocá-lo para xpath
alterar o valor literal dos nomes dos nós.