xml_grep 要素を含む要素を除外する

xml_grep 要素を含む要素を除外する

XMLファイルから特定の要素を含むすべての要素を削除しようとしています。以下は私がやろうとしていることの非常に簡略化されたバージョンです。次のようなXMLファイルがあるとします。

<RootEl>
   <A>
      <B/>
   </A>
   <A>
      <C/>
   </A>
 </RootEl>

B を含む A だけをすべて保持したい場合は、次のコマンド ラインを使用できます。

xml_grep -root A -cond B < TheFile.xml

しかし、逆にBを含まないAだけを残したい場合、困ってしまいます。上記と同様のコマンド、つまり

xml_grep -root A -exclude B < TheFile.xml

私に与える

<RootEl>
   <A>

   </A>
   <A>
      <C/>
   </A>
 </RootEl>

私が望んでいるのは

<RootEl>
   <A>
      <C/>
   </A>
 </RootEl>

同じ望ましくない答えが返ってきます

xml_grep -root A -exclude A/B < TheFile.xml

または

xml_grep -exclude A/B < TheFile.xml

Python でこれを行う方法はわかりましたが、おそらく xslt でも可能だと思います。しかし、xml_grep でこれを行う方法を期待していました。

ところで、なぜ C を含む A が欲しいと言わないのかと誰かが尋ねるでしょう。問題は、A には B や C 以外にも 20 種類ほどのものが含まれるため、C や D、あるいは Z を含む A を指定しなければならないことです。これは、AI が欲しくない 1 種類のものを指定するよりもはるかに手間がかかります。

質問特定の要素を含むXMLノードを削除する基本的に同じ質問をしていますが、xml_grep を使用した回答はありません。xml_grep はかなり人気があり、このような目的のために構築されているようなので、誰かがそのような回答を提案してくれることを期待しています...ほぼ。

答え1

使用方法xmlstarlet:

$ xmlstarlet ed -d '//A[not(B)]' file.xml
<?xml version="1.0"?>
<RootEl>
  <A>
    <B/>
  </A>
</RootEl>

XPATH 式は、子ノードとしてノードを含まないドキュメント内の//A[not(B)]すべてのノードを選択します。選択されたノードは削除されます。AB

//A[not(child::B)]この表現は、もう少し明確にすると と書くこともできます。

関連情報