XMLファイルがあります。読んでるだけでワクワクしてきます。
完全に削除したいタグがいくつかあります。
<qwerty option=1>
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
これは大きなファイルです。nmo
すべてのタグとblue
をその内容を含めて削除するにはどうすればよいですか? Emacs、または私のMacが使用できるその他のもの。
Emacsには、シンボリック式または「sexps」をナビゲートするためのコマンドがあります。ではxml-mode
、sexpナビゲーションコマンドはタグで機能します。開口部に移動するか、 ( )を<
押してタグの最後に移動するか、()を押してタグを削除できます。変数は、開始タグの終わり(デフォルト)に移動するか、終了タグの最後に移動するかを制御します。私は後者が好きです。C-M-fforward-sexp
C-M-kkill-sexp
nxml-sexp-element-flag
これらのタグを削除するには、最初に。を設定nxml-sexp-element-flag
しM-x customize-variable nxml-sexp-element-flagます。次に、殺したいタグを検索し、ポイントを開口部に移動して、<
を押しC-M-kます。これをすべてマクロにまとめ、検索が失敗するまでファイル全体を繰り返します。
より一般的なアプローチは、XSL(T)のようなXML指向のツールを使用することだと思います(恐れることはありません、誰もそれを好きではありません)が、XMLを使用する必要がある場合は便利です(恐れることはありません、誰もそれを好きではありません)。
だから、ここに行きます:
これはXSLファイルです(元のXMLのすべてのものをコピーし、削除したいノードを空の行に置き換えます。最後に、それを印刷して、いくらかきれいに見せます。次に、正規表現を使用して置き換えた場合。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copy everything -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Find any node named nmo or blue and replace it with nothing -->
<xsl:template match="nmo | blue"/>
</xsl:stylesheet>
これは私がテストするために使用した私の例です:
<?xml version="1.0" encoding="utf-8"?>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
</nodes>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<other node=""/>
<nodes>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
<qwerty option="1">
<nmo>sdfsdf</nmo>
<blue>sdfsdf</blue>
</qwerty>
</nodes>
</nodes>
</nodes>
そして、これは私が受け取っている出力です:
<?xml version="1.0"?>
<nodes>
<qwerty option="1"/>
<nodes>
<qwerty option="1"/>
</nodes>
<nodes>
<qwerty option="1"/>
<other node=""/>
<nodes>
<qwerty option="1"/>
<qwerty option="1"/>
<qwerty option="1"/>
</nodes>
</nodes>
</nodes>
qwerty
ノードも閉じていることに注意してください。
これを取得するためのコマンドラインは次のようになります。
xsltproc ./remove-nodes.xsl ./nodes-to-be-removed.xml > result.xml
Emacsのシェルから実行するか、Emacsの関数のいずれかを使用してそれを呼び出したり、それを使用してプロセスを作成したりすることができます。man xsltproc
詳細については、使用法は本当に基本的です。それは私のFedoraにインストールされましたが、世界中にXMLが広まっているため、すでにMacにインストールされているか、何らかの方法でインストール可能である必要があると思います。
あなたのxmlファイルは整形式だと思います。また、あなたの例とは反対に、「実際の」データは、1行に1つのタグよりも少し複雑であると思います(ルートのものを除く)。そうでなければ、特定のタグを含む行を削除するのと同じくらい簡単だと思いますか?
トリックを実行できる関数の命題を次に示します。
(defun my-remove-tag (tag)
(save-excursion
(let ((case-fold-search nil))
(while (search-forward-regexp (concat "<" tag "[^\\>]*>"))
(delete-region
(match-beginning 0)
(search-forward (concat "</" tag ">")))))))
nmo
この関数を呼び出すと、次のように、blue
またはqwerty
タグを探すことができます。
(my-remove-tag "nmo")
(my-remove-tag "qwerty")
理論的根拠は、開始タグを探してから終了タグを探し、途中のすべてを削除することです。タグの属性は途中で入る可能性があり、この関数は属性を含む開始タグを処理します。
関数が完了すると、大文字と小文字の区別は無効になり、復元されます。また、Emacs Point は通常のマクロ : で復元されますsave-excusion
。
アウターレットを外しました。case-fold-search 値を手動で復元する必要はありません。 let バインディングは単にグローバル値をシャドウします。これは「シャドウイング解除」によって復元されます。