一部の指定タグの特定の文字列を、XMLファイルのタグに含まれる他の文字列に置き換える必要があります。
が表示されるすべての項目を検索し、タグ内(他のタグ内)がある場合にのみ、次のようにan example
置き換える必要があります。<b>a test</b>
<a> ... </a>
- 入力例:
<c>This is an example. <a>This is an example;</a></c>
- 希望の出力:
<c>This is an example. <a>This is <b>a test;</b></a></c>
答え1
あなたが望むようです
- XMLドキュメントのノード値
an example;
からテキストを削除し、/c/a
/c/a
名前付きノードにb
値を持つ子ノードを追加しますa test;
。
xmlstarlet
シェルでこれを簡単に実行できます。
xmlstarlet ed -u '/c/a' -x 'substring-before(text(), "an example;")' file.xml |
xmlstarlet ed -s '/c/a' -t elem -n 'b' -v 'a test;'
xmlstarlet
質問のサンプル文書への最初の呼び出しは、ノード/c/a
値からいくつかのテキストを削除して出力を生成します。
<?xml version="1.0"?>
<c>This is an example. <a>This is </a></c>
2番目の呼び出しはこの修正された文書を取得し、ノードを導入して次のように生成します/c/a/b
。
<?xml version="1.0"?>
<c>This is an example. <a>This is <b>a test;</b></a></c>
これらのxmlstarlet
呼び出しは単一のコマンドにまとめることができます。以下では--inplace
、元の文書の内部編集にも長いオプションを使用しました(これは説明のためのものであるため、--inplace
変換が機能していることを確認するには、まず実行せずに実行する必要があります)。
xmlstarlet ed --inplace \
--update '/c/a' -x 'substring-before(text(), "an example;")' \
--subnode '/c/a' -t elem -n 'b' -v 'a test;' file.xml
上記の内容を一般化して、a
テキストを含むノードで2つの編集を行いますan example;
(質問で実際に必要なものです)。
xmlstarlet ed \
--var paths '//a[contains(text(), "an example;")]' \
--update '$paths' -x 'substring-before(text(), "an example;")' \
--subnode '$paths' -t elem -n 'b' -v 'a test;' file.xml
ここで唯一の新しいことは、編集したいすべてのノードのパスを最初に内部変数に保存することです$paths
。次に--update
、これらのパスを参照して変更します--subnode
。