空の属性を持つXMLタグの削除

空の属性を持つXMLタグの削除

入力ファイル:

<ServiceArea type="STATE" value="DC">
    <DaylightSavingsUsed value="true"/>
    <FemtoSipProxyAddress value="10.13.123.100"/>
    <TermAuthAAAPSK value="secret1"/>
    <PDSNDOParams index="1">
        <batchEndIpAddress value="68.28.121.68"/>
        <batchSecurityParameterIndex value="5262006"/>
        <batchStartIpAddress value="68.28.121.68"/>
    </PDSNDOParams>
    <PDSNDOParams index="2">
        <batchEndIpAddress value="68.28.113.68"/>
        <batchIOSVersion value="tia-878-a"/>
        <batchStartIpAddress value="68.28.113.68"/>
    </PDSNDOParams>
    <PDSN1XParams index="1">
        <batchEndIpAddress value="68.28.121.68"/>
        <batchSecretKey value="72563130317354663167345439615433"/>
        <batchSecurityParameterIndex value="5262006"/>
        <batchStartIpAddress value="68.28.121.68"/>
    </PDSN1XParams>
    <PDSN1XParams index="2">
        <batchEndIpAddress value="68.28.113.68"/>
        <batchIOSVersion value="tia-878-1"/>
    </PDSN1XParams>
</ServiceArea>

<ServiceArea type="ZIP" value="66221">
</ServiceArea>

<ServiceArea type="FIPS" value="46081">
    <DaylightSavingsUsed value="true"/>
    <MTA_Number value="22"/>
    <BC10_Utilization value="476,487,526"/>
</ServiceArea>

<ServiceArea type="FIPS" value="01824">
</ServiceArea>

間にデータがないすべての行を削除したいと思います。

<ServiceArea type=
</ServiceArea>

上記の入力から以下を削除する必要があります。

<ServiceArea type="ZIP" value="66221">
</ServiceArea>

そして

<ServiceArea type="FIPS" value="01824">
</ServiceArea>

答え1

スクリプト(スタイルシートとも呼ばれます)をxsltproc使用してXMLファイルを処理できます。xsltこれには xslt スクリプトと制御 bash スクリプトが含まれます。たとえば、

dropem.xslt

 <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="ServiceArea">
    <xsl:if test="count(*)>0">
      <ServiceArea>
        <xsl:copy-of select="node()"/>
      </ServiceArea>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

dropem.sh

#!/bin/bash
cat <<EOF | xsltproc dropem.xslt - | tail -n +2
<ALL>
$(cat)
</ALL>
EOF

実際のコマンドは次のとおりです。

./dropem.sh < infile > outfile

注:xsltスクリプトには、ServiceAreaノードと一致する「テンプレート」要素が含まれており、条件に基づいて(子ノードがある場合)それを結果にコピーします。

xsltproc単一のXMLツリーのみが処理されるため、入力は閉じたタグペアでラップする必要があります。パッケージングは​​データファイルをツリーにします。改行は出力に保持されず、出力はServiceAreaサブツリーのリストでもあります。

<?xml ...ただし、必然的なプリアンブルと空の行の放出を防ぐために、出力は切り捨てられます。xsltproc

このアプローチの利点は、入力ファイルの行形式にあまり敏感でないことです。欠点は、あまりxslt一般的でない言語を使用することです。

答え2

ノードをxmlstarlet検出する方法に応じて、さまざまな方法でこれを実行できます。ServiceArea

  • すべてのServiceArea「テキストノード」ノードを削除します。

    xmlstarlet ed -d '//ServiceArea[text()]' file.xml
    
  • ServiceArea子なしのすべてのノードを削除します。

    xmlstarlet ed -d '//ServiceArea[count(*)=0]' file.xml
    

どちらも文書形式が正しいかどうかによって異なります。サンプル文書には複数のルートノードが含まれているため、そうではありません。この問題を解決するのは簡単です。たとえば、文書の<root>先頭と末尾に追加します。</root>

答え3

誰もが正しいXML解析ツールを使用してxmlを編集するように言うでしょうが、ServiceAreaタグが別々の行にあると仮定する簡単なawkスクリプトです。

awk '/<ServiceArea /{save = $0; next}
    save!="" {
       if(/<\/ServiceArea>/){ save = ""; next }
       print save
       save = ""
    }
    { print }'

これにより、行が表示されたときに開始タグと一緒に保存されます。次の行を読み取るときに保存された行がありますが、現在の行が終了マークの場合は両方の行を抑制します。それ以外の場合は、保存した行を印刷してから現在の行を印刷します。

関連情報