我想從 shell 添加命名空間前綴到 XML 文件的預設命名空間的標籤

我想從 shell 添加命名空間前綴到 XML 文件的預設命名空間的標籤

我有一個 SVG 文件,它是一個 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>

我想將 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>

我確信這可以在 shell 的一個或幾個命令列中使用xmllint和/或xmlstarlet但我無法管理它。

答案1

自從你問起以來已經有一段時間了。儘管如此 ...

xmlstarlet edit's -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, --varwithout =, ao)
  • 在列出生成的 XSLT 程式碼之前新增一個-C選項-t

輸出:

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

在哪裡

  • -P/--pf保留原始格式
  • 在支援就地編輯 後新增-L/選項(不在使用者指南中,而是在--inplaceeditxmlstarlet.txt

要將輸出作為 shell 腳本執行:

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更改節點名稱的文字值。

相關內容