Ich möchte den Tags des Standard-Namespace eines XML-Dokuments aus der Shell ein Namespace-Präfix hinzufügen

Ich möchte den Tags des Standard-Namespace eines XML-Dokuments aus der Shell ein Namespace-Präfix hinzufügen

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 editDie Aktion -r/ --renameerfordert 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-Funktionset:distinct eliminiert Duplikate
  • -ogibt einen Stringliteral, -neinen Zeilenumbruch und -fden Eingabepfad/die URL aus (außer -für stdin)
  • -bbeendet den aktuellen Container ( -m, --varohne =, ao)
  • Hinzufügen einer -COption vor -tden Listen des generierten XSLT-Codes

Ausgabe:

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

Wo

  • -P/ --pfbehält die ursprüngliche Formatierung bei
  • Das Hinzufügen einer -L/ --inplace-Option nach editunterstü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 uniqoder einfach -m '//_:*'mit möglichen Duplikaten.

Antwort2

xmlstarletBesonders 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 xpathden Literalwert der Knotennamen zu ändern.

verwandte Informationen