シェルでは、XML文書のデフォルトの名前空間タグに名前空間接頭辞を追加したいと思います。

シェルでは、XML文書のデフォルトの名前空間タグに名前空間接頭辞を追加したいと思います。

XML文書であるSVGファイルがあります。

<?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>

次の出力を得るために、デフォルトの名前空間に対応するすべてのタグにsvg:プレフィックスを追加したいと思います。

<?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>

私はこれがシェルの1つまたは複数のコマンドラインで使用できると確信しています。xmllintそして/またはxmlstarletしかし、私はそれを管理することはできません。

答え1

質問してからかなり時間が経ちました。それにもかかわらず...

xmlstarlet edit-r/--rename操作には新しい名前のリテラル値が必要なため、XPath機能は機能しなくなりました。ただし、xmlstarlet select 編集コマンドを生成するためのコードジェネレータとして使用できます。

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 

どこ

  • 式は、//_:*デフォルトの名前空間のすべての要素ノードと一致します(ショートカット_は次の場所にあります)。xmlstarlet ユーザーマニュアル)
  • EXSLT機能set:distinct 重複排除
  • -o出力文字列リテラル、改行、-n入力-fパス名/ URL(ただし、-標準入力の場合)
  • -b現在のコンテナ終了(-m--varなし=、ao)
  • 生成されたXSLTコードをリストする前に、-Cオプションを追加してください。-t

出力:

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

どこ

  • -P/--pf元の形式を保持
  • 内部編集サポート後-L/オプションの追加(ユーザーガイドにはありませんが、--inplaceeditxmlstarlet.txt)

出力をシェルスクリプトとして実行するには:

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

EXSLTを回避するには、代わりに-m '//_:*' --sort 'A:T:-' . 出力をパイプするuniq-m '//_:*'、可能な冗長性を使用してください。

答え2

xmlstarlet特に残酷な方法で使用される(正しい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

名前空間を宣言したので、svgそれを呼び出してxpathノード名のリテラル値を変更する必要があります。

関連情報