
Ich habe eine SVG-Datei, die ein XML-Dokument ist:
<?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>
Ich möchte allen Tags, die dem Standardnamespace entsprechen, das Präfix svg: hinzufügen, um die folgende Ausgabe zu erhalten:
<?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>
Ich bin sicher, dass dies mit einer oder wenigen Befehlszeilen von der Shell aus möglich ist,xmllintund/oderxmlstarletaber ich schaffe es nicht.
Antwort1
Es ist eine Weile her, seit Sie gefragt haben. Trotzdem ...
xmlstarlet edit
Die Aktion -r
/ --rename
erfordert einen Literalwert für den neuen Namen, sodass XPath-Funktionen nicht infrage kommen. xmlstarlet select
Kann jedoch als Codegenerator verwendet werden, um den Bearbeitungsbefehl zu erzeugen:
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
Wo
- der
//_:*
Ausdruck trifft auf alle Elementknoten im Standard-Namespace zu (die_
Verknüpfung befindet sich imxmlstarlet
Bedienungsanleitung) - die EXSLT-Funktion
set:distinct
eliminiert Duplikate -o
gibt einen Stringliteral,-n
einen Zeilenumbruch und-f
den Eingabepfad/die URL aus (außer-
für stdin)-b
beendet den aktuellen Container (-m
,--var
ohne=
, ao)- Hinzufügen einer
-C
Option vor-t
den Listen des generierten XSLT-Codes
Ausgabe:
xmlstarlet edit --pf \
-r '//_:svg' -v 'svg:svg' \
-r '//_:defs' -v 'svg:defs' \
file.xml
Wo
-P
/--pf
behält die ursprüngliche Formatierung bei- Das Hinzufügen einer
-L
/--inplace
-Option nachedit
unterstützt die Bearbeitung direkt vor Ort (nicht im Benutzerhandbuch, sondern in xmlstarlet.txt)
So führen Sie die Ausgabe als Shell-Skript aus:
xmlstarlet-select-command | sh -s > result.xml
Falls Sie EXSLT vermeiden möchten, -m '//_:*' --sort 'A:T:-' .
leiten Sie die Ausgabe stattdessen weiter uniq
oder einfach -m '//_:*'
mit möglichen Duplikaten.
Antwort2
xmlstarlet
Besonders brutale Verwendung (ich warte auf den richtigen XPath)
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
Da Sie den Namespace bereits deklariert haben svg
, müssen Sie ihn aufrufen, um xpath
den Literalwert der Knotennamen zu ändern.