タグに基づいてxmlファイルの名前を変更する

タグに基づいてxmlファイルの名前を変更する

XMLファイルがたくさんあります。tag1="alpha"たとえば、XMLの特定のタグに基づいて各タグの名前を変更する必要があります。

私はそれに基づいてそれを行う方法を見つけました。一つ特定のタグの発生。

find . -maxdepth 1 -name '*.xml' -exec /rename.sh {} \;
#!/bin/bash

tag1=$(sed 's/.*tag1="\([^"]*\).*/\1/; q' "$1")
mv -v "$1" "$tag1.xml"

問題:一部のファイルには複数のtag1タグがあります(例:)。これらのファイルの場合は、tag1="alpha" tag1="beta" tag1="omega"同じファイルのコピーを別の名前で作成する必要がありますbeta.xmlomega.xml

catの位置パラメータを試しましたが、うまくいきません(初心者です)。

ファイル構造の例:

<root xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">

<div class="div-entry"><d:entry xmlns:d="1.0.rng" id="m_en_gbus0240000" tag1="cudgel" class="entry">
 <span class="hg x_xh0">
   <span role="text" d:syl="1" class="hw">cudg.el<d:syl/></span>
   <span prxid="cudgel_us_nv" prlexid="pron0014256.002" dialect="AmE" class="prx"> | <span d:prn="US" dialect="AmE" class="ph t_respell">ˈ;ke;je;l<d:prn/></span><span d:prn="IPA" soundFile="cudgel#_us_1" media="online" dialect="AmE" class="ph">ˈ;ke;d&#658;e;l<d:prn/></span> | </span>
 </span>
 <span class="sg">
   <span id="m_en_gbus0240000.004" class="se1 x_xd0">
     <span role="text" class="posg x_xdh">
       <span d:pos="1" class="pos">
         <span class="gp tg_pos">noun </span>
         <d:pos/>
       </span>
     </span>
     <span id="m_en_gbus0240000.005" class="msDict x_xd1 t_core">
       <span d:def="1" role="text" class="df">a short, thick stick used as a weapon<span class="gp tg_df">. </span><d:def/></span>
     </span>
     <span class="gp x_xdt tg_se1"> </span>
   </span>
   <span id="m_en_gbus0240000.008" class="se1 x_xd0">
     <span class="x_xdh">
       <span role="text" class="posg">
         <span d:pos="2" class="pos">
           <span class="gp tg_pos">verb </span>
           <d:pos/>
         </span>
         <span class="infg"><span class="gp tg_infg">(</span><span tag1="cudgels", <span tag1="cudgeling"<span class="pr"/>, <span tag1="cudgeled"<span class="pr"/>; <span class="lg"><span class="ge">British </span></span><span tag1="cudgels", <span tag1="cudgelling", <span tag1="cudgelled"<span class="gp tg_infg">) </span></span>
       </span>
       <span role="text" class="gg"><span class="gp tg_gg">[</span>with <span class="sy">object</span><span class="gp tg_gg">] </span></span>
     </span>
     <span id="m_en_gbus0240000.011" class="msDict x_xd1 t_core">
       <span d:def="2" role="text" class="df">beat with a cudgel<d:def/></span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> they would lie in wait and cudgel her to death</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
   </span>
   <span class="gp tg_sg"> </span>
 </span>
 <span class="subEntryBlock x_xo0 t_phrases">
   <span class="gp x_xoLblBlk ty_label tg_subEntryBlock">PHRASES </span>
   <span id="m_en_gbus0240000.022" class="subEntry x_xo1">
     <span class="x_xoh">
       <span role="text" tag1="cudgel one's brains "
       <span class="vg"><span class="gp tg_vg">(</span>also <span id="m_en_gbus0240000.037" tag1="cudgel one's brain"<span class="gp tg_vg">) </span></span>
     </span>
     <span id="m_en_gbus0240000.024" class="msDict x_xo2 t_core">
       <span role="text" class="lg">
         <span class="ge">British </span>
       </span>
       <span role="text" class="df">think hard about a problem</span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> she cudgeled her brains, trying to decide what had caused such an about-face</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
     <span class="gp x_xot tg_subEntry"> </span>
   </span>
   <span id="m_en_gbus0240000.025" class="subEntry x_xo1">
     <span role="text" tag1="take up the cudgels "
     <span id="m_en_gbus0240000.026" class="msDict x_xo2 t_core">
       <span role="text" class="df">start to defend or support someone or something strongly</span>
       <span role="text" class="gp tg_df">: </span>
       <span role="text" class="eg">
         <span class="ex"> there was no one else to take up the cudgels on their behalf</span>
         <span class="gp tg_eg">. </span>
       </span>
     </span>
   </span>
 </span>
 <span role="text" class="etym x_xo0">
   <span class="gp x_xoLblBlk ty_label tg_etym">ORIGIN </span>
   <span class="x_xo1"><span class="dg"><span class="date">Old English </span></span><span class="italic">cycgel</span>, of unknown origin<span class="gp tg_etym">.</span></span>
 </span>
</d:entry>
<div class="div-entry"><div>

</root>

ベストアンサー1

なぜ使用しないのですか?xmlstarletフレーズを抽出 tag1し、シェルスクリプトループから出力を処理します。

xmlstarlet select 複数のパス名を入力として受け入れるので、{} +より効率的なsバリアントで使用できます。find-exec オペランド。常に true と評価されるため、-exec … {} +ゼロ以外の終了状態では中断されません。tag1変換されたフレーズとともにファイル名をリストするには、次のようにします。

# shellcheck shell=sh disable=SC2016

find . -maxdepth 3 -type f -name '*.xml' -exec \
  xmlstarlet select --text -t \
    --var tag1nodes='//@tag1[name(..)="span" or name(..)="div"]' \
    --var allowchars -o 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' -b \
    --var tag1cvt -o 'translate(normalize-space(),translate(.,$allowchars,""),"_")' -b \
    -m 'set:distinct(dyn:map($tag1nodes,$tag1cvt))' \
      -s 'A:T:-' '.' \
      -f -o "${ofs:-$(printf '\t')}" -v '.' -n \
  {} +

xmlstarlet selectコマンドの説明

  • select最初の入力ファイルのルート要素にある名前空間定義(および事前定義されたEXSLTの名前空間)を使用してxsl参照さsaxonれる他のすべての名前空間は、オプションを使用して定義-Nする必要があります。
  • 変数は、または要素から構文(属性値)を収集しますtag1nodestag1divspan推定デフォルトの名前空間または空の同じ場所に配置
  • EXSLTdyn:maptag1cvtこの関数は引数(テキスト文字列として提供されたXPath式)を評価して、各構文を文字列にマップします。
    • 巻き先行、末尾、冗長スペース
    • 変える_(アンダースコア)を含む英数字以外の文字、仮説Cロケール
  • EXSLTset:distinct重複排除
  • ソート順は、A昇順、T拡張、未指定のケースの順序です。
  • tag1その値がない場合、出力は生成されません。 (この場合は1が返されますselect。)
  • -C使用する-tXSLT 1.0スタイルシートを一覧表示するオプションを追加する前にselect
  • ここで定義は--var読みやすくするために追加され、dyn:mapパラメータで簡単に置き換えることができます。
  • パス名はfind以下に由来します。推定いいえ
    • '(一重引用符)文字のため既知のエラー 存在するselect
    • 空白(出力を処理するシェルスクリプトがデフォルト値をIFS使用する場合)read

いくつかのサンプル出力:

./dir-b/fum.xml cudgels
./dir-b/fum.xml take_up_the_cudgels
./fee.xml       cudgel_ones_brain
./fee.xml       cudgel_ones_brains
./fee.xml       cudgeled
./fee.xml       cudgeling
./fee.xml       cudgelled
./fee.xml       cudgelling

公開したファイルはXMLではありませんが、xmlstarletその内容を回復できます(-qエラーリストを省略)。

xmlstarlet -q format -R junk > file.xml

おすすめ記事