sed ツールを使用せずに (サブタグの) パターンを探し、XML ファイル内の完全な親タグを置き換えます。

sed ツールを使用せずに (サブタグの) パターンを探し、XML ファイル内の完全な親タグを置き換えます。

正規表現を使用して子タグのパターンを見つけ、全体の親タグを置き換える方法はありますか?私はグラフィック環境のないLinuxサーバーで作業しています。

次のXMLがあります。

<?xml version="1.0" encoding="UTF-8"?>  
<bookstore>  
  <book category="COOKING">  
    <title lang="en">Everyday Italian</title>  
    <author>Giada De Laurentiis</author>  
    <year>2005</year>  
    <price>30.00</price>  
  </book>  
  <book category="CHILDREN">  
    <title lang="en">Harry Potter</title>  
    <author>J K. Rowling</author>  
    <year>2005</year>  
    <price>29.99</price>  
  </book>  
  <book category="WEB">  
    <title lang="en">Learning XML</title>  
    <author>Erik T. Ray</author>  
    <year>2003</year>  
    <price>39.95</price>  
  </book>  
</bookstore>  

パターンを見つけるためのシェルスクリプトが必要です。

<author>J K. Rowling</author>

その後、ブロック全体を交換します。

  <book category="CHILDREN">  
    <title lang="en">Harry Potter</title>  
    <author>J K. Rowling</author>  
    <year>2005</year>  
    <price>29.99</price>  
  </book>  

そして:

  <book category="CHILDREN">  
    <title lang="en">Hamlet</title>  
    <author>William Shakespeare</author>  
  </book>

ついに得た:

<?xml version="1.0" encoding="UTF-8"?>  
<bookstore>  
  <book category="COOKING">  
    <title lang="en">Everyday Italian</title>  
    <author>Giada De Laurentiis</author>  
    <year>2005</year>  
    <price>30.00</price>  
  </book>  
  <book category="CHILDREN">  
    <title lang="en">Hamlet</title>  
    <author>William Shakespeare</author>  
  </book>  
  <book category="WEB">  
    <title lang="en">Learning XML</title>  
    <author>Erik T. Ray</author>  
    <year>2003</year>  
    <price>39.95</price>  
  </book>  
</bookstore> 

同様に、 との間のすべてのテキストまたはコードのワイルドカード<book*<author>J K. Rowling</author>*</book>はどこにありますか?*<book<author>...

Perlを使用して次の論理ステップを考慮するアイデアがあります。

  1. 検索パターンが配置されている行番号
  2. 親ブロックのオープンタグとクローズタグの行番号を識別します。
  3. この行内のすべての内容を削除します。
  4. この行に新しいブロックを追加してください。

しかし可能です。私は最初のアプローチを好みます。

答え1

私が好む方法は、しばしばxmlstarletXMLデータを使って作業することです。編集する必要があるサブツリーを参照するxmlstarlet変数を宣言します。$book

xmlstarlet <682660.xml ed                                               \
    --var book '//book[author="J K. Rowling"]'                          \
    --update '$book' --value ''                                         \
    --update '$book/@category' --value 'CHILDREN'                       \
    --subnode '$book' --type 'elem' --name 'title'  --value 'Hamlet'    \
    --subnode '$book/title' --type attr --name 'lang' --value 'en'      \
    --subnode '$book' --type 'elem' --name 'author' --value 'William Shakespeare'

出力

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Hamlet</title>
    <author>William Shakespeare</author>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

関連する<book/>サブツリーを削除して新しいサブツリーを追加することもできますが、これは順次処理を中断する可能性があるため、ここではそうしませんでした。

答え2

構造化文書形式で作業するときは、これらの形式で機能するように設計されたツールを使用してください。正規表現は主にテキストを一致させるために使用され、XML文書は実際にはテキストではありませんが、特定の方法で構造化されたデータです(改行などは必ずしも重要ではありません)。繰り返しますが、sedこれはテキスト行を処理するためのツールですが、通常XMLはそうではありません。

xq以下で使用https://kislyuk.github.io/yq/

xq -x '.book as $new | input |
    (
        .bookstore.book[] |
        select(.author == "J K. Rowling")
    ) |= $new' insert.xml file.xml

XMLと挿入する要素をxqJSONに変換するために使用されます。次に、生成されたJSON文書に特定の式を適用して、配列内の各項目を抽出します。その後、まったく同じフィールドを持つその配列のすべての要素が読み取られた要素に置き換えられます。bookstoreinsert.xmljq.bookstore.book.authorJ K. Rowlinginsert.xml

詳しくは、新しいオブジェクトの内容を.book内部変数と呼ばれる内部変数として読み込み、次に呼び出して$new基本文書を取得しますinput。このselect()ステートメントは.bookstore.book配列内の個々の要素ごとに機能し、特定の作成者を持つ要素を抽出します。結果は、一致する項目に対する複数の「パス」ですbook。 (更新演算子)を使用して、以前に生成された値|=で更新します$new

ファイルを介さずにコマンドラインから新しいXMLを提供するには、次のマニュアルを使用してください。

xq -x '.book as $new | input |
    (
        .bookstore.book[] |
        select(.author == "J K. Rowling")
    ) |= $new' - file.xml <<'NEW_XML'
<book category="CHILDREN">
  <title lang="en">Hamlet</title>
  <author>William Shakespeare</author>
</book>
NEW_XML

入力ファイル名はinsert.xmlコマンドラインでダッシュに置き換えられます。

あなたの質問のデータに基づいて結果は次のとおりです。

<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="CHILDREN">
    <title lang="en">Hamlet</title>
    <author>William Shakespeare</author>
  </book>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

このユーティリティは、対応する(または)オプションを使用するとxq内部編集を有効にします。--in-place-i


参考までに、xqXMLは次の内部JSON表現に変換され、次のように処理されますjq

{
  "bookstore": {
    "book": [
      {"@category":"COOKING","title":{"@lang":"en","#text":"Everyday Italian"},"author":"Giada De Laurentiis","year":"2005","price":"30.00"},
      {"@category":"CHILDREN","title":{"@lang":"en","#text":"Harry Potter"},"author":"J K. Rowling","year":"2005","price":"29.99"},
      {"@category":"WEB","title":{"@lang":"en","#text":"Learning XML"},"author":"Erik T. Ray","year":"2003","price":"39.95"}
    ]
  }
}

挿入するデータは同等の内容に変換されます。

{
  "book": {
    "@category": "CHILDREN",
    "title": {
      "@lang": "en",
      "#text": "Hamlet"
    },
    "author": "William Shakespeare"
  }
}

関連情報