kshのキーワードを使用してxmlファイルからxmlチャンクをgrepする方法

kshのキーワードを使用してxmlファイルからxmlチャンクをgrepする方法

多くのサービスを含むSample.xmlファイルがあり、その構造は次のとおりです。

メモ:

  1. 読み取り専用権限がないため、XMLパーサーツールは使用できません。

  2. 私のxmllintバージョンはxpathをサポートせずに更新できず、読み取り専用です。

  3. xmlstarletがないためインストールできません。

質問:入力:キュー名

出力:サービスブロック

入力例:ABC.getme2

希望の出力:

<service name="GETME2" min="1" max="10" idleTime="300" backend="ABC">
                            <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                            <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                            </handlerContainer>
                            <mqListener queue="ABC.getme2" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                    </service>

XML構造:

     <?xml version="1.0" encoding="UTF-8"?>
        <deploymentconfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <configfile>sample.xml</configfile>
                <exceptionsFilterConfigFile>asdasd.xml</exceptionsFilterConfigFile>
                <keyInfoConfigFile>asdasd.xml</keyInfoConfigFile>
                <services>

    <service name="GETME" min="1" max="10" idleTime="300" backend="ABC">
                            <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                            <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                            </handlerContainer>
                            <mqListener queue="ABC.getme" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                    </service>

    <service name="GETME2" min="1" max="10" idleTime="300" backend="ABC">
                            <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                            <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                            </handlerContainer>
                            <mqListener queue="ABC.getme2" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                    </service>
        . . . .a lot of services like this . . . .
        . . . .a lot of services like this . . . .
        . . . .a lot of services like this . . . .
        . . . .a lot of services like this . . . .
        </services>
   <batchServices>
                        <batchService name="batch1">
                                <executor className="com.abc.xyz.qwer.qweqwewqe.ffdsdfsdfsdfsdf" />
                        </batchService>
                        <batchService name="batch2">
                                <executor className="com.abc.xyz.qwer.qweqwewqe.zxcsadsad" />
                        </batchService>
. . . .a lot of batch services like this . . . .
        . . . .a lot of batch services like this . . . .
        . . . .a lot of batch services like this . . . .
        . . . .a lot of batch services like this . . . .
      </batchServices>

<timerservices>
<timerservice> - a lot of timeservice
</timerservices>

  <connectionPools>
                <pool>
                        <name>asdasd</name>
                        <driver>oracle.jdbc.driver.OracleDriver</driver>
                        <url>$asdasd_URL</url>
                        <userId>$asdasd_USER</userId>
                        <password>$asdasd_PASSWORD</password>
                        <minConnections>0</minConnections>
                        <maxConnections>10</maxConnections>
                        <poolUrl>jdbc:asdsad:asdasdsad</poolUrl>
                        <testSql>select * from abc</testSql>
                </pool>

 . . a lot of pools. . .

</connectionpools>

</deploymentconfig>

次のようにXML塊をgrepする必要があります。

 <service name="GETME" min="1" max="10" idleTime="300" backend="ABC">
                        <handlerContainer className="com.abc.xyz.wqere.abcqwere">
                        <handler className="com.abc.xyz.qweqweqwe.werwerwerwer"/>
                        </handlerContainer>
                        <mqListener queue="ABC.getme" suggExpiry="30" minExpiry="4" maxExpiry="500" copyMessageId="true"/>
                </service>

キュー名を指定するだけです。

QUEUENAME=INSERT_HERE
grep ______________ $QUEUENAME. . . 

出力は次のとおりです。

Usage : xmllint [options] XMLfiles ...
    Parse the XML files and output the result of the parsing
    --version : display the version of the XML library used
    --debug : dump a debug tree of the in-memory document
    --shell : run a navigating shell
    --debugent : debug the entities defined in the document
    --copy : used to test the internal copy implementation
    --recover : output what was parsable on broken XML documents
    --noent : substitute entity references by their value
    --noout : don't output the result tree
    --path 'paths': provide a set of paths for resources
    --load-trace : print trace of all external entites loaded
    --nonet : refuse to fetch DTDs or entities over network
    --nocompact : do not generate compact text nodes
    --htmlout : output results as HTML
    --nowrap : do not put HTML doc wrapper
    --valid : validate the document in addition to std well-formed check
    --postvalid : do a posteriori validation, i.e after parsing
    --dtdvalid URL : do a posteriori validation against a given DTD
    --dtdvalidfpi FPI : same but name the DTD with a Public Identifier
    --timing : print some timings
    --output file or -o file: save to a given file
    --repeat : repeat 100 times, for timing or profiling
    --insert : ad-hoc test for valid insertions
    --compress : turn on gzip compression of output
    --html : use the HTML parser
    --xmlout : force to use the XML serializer when using --html
    --push : use the push mode of the parser
    --memory : parse from memory
    --maxmem nbbytes : limits memory allocation to nbbytes bytes
    --nowarning : do not emit warnings from parser/validator
    --noblanks : drop (ignorable?) blanks spaces
    --nocdata : replace cdata section with text nodes
    --format : reformat/reindent the input
    --encode encoding : output in the given encoding
    --dropdtd : remove the DOCTYPE of the input docs
    --c14n : save in W3C canonical format (with comments)
    --exc-c14n : save in W3C exclusive canonical format (with comments)
    --nsclean : remove redundant namespace declarations
    --testIO : test user I/O support
    --catalogs : use SGML catalogs from $SGML_CATALOG_FILES
                 otherwise XML Catalogs starting from 
             file:///etc/xml/catalog are activated by default
    --nocatalogs: deactivate all catalogs
    --auto : generate a small doc on the fly
    --xinclude : do XInclude processing
    --noxincludenode : same but do not generate XInclude nodes
    --loaddtd : fetch external DTD
    --dtdattr : loaddtd + populate the tree with inherited attributes 
    --stream : use the streaming interface to process very large files
    --walker : create a reader and walk though the resulting doc
    --pattern pattern_value : test the pattern support
    --chkregister : verify the node registration code
    --relaxng schema : do RelaxNG validation against the schema
    --schema schema : do validation against the WXS schema
    --schematron schema : do validation against a schematron
    --sax1: use the old SAX1 interfaces for processing
    --sax: do not build a tree but work just at the SAX level

Libxml project home page: http://xmlsoft.org/
To report bugs or get some help check: http://xmlsoft.org/bugs.html

これはバージョンです

xmllint: using libxml version 20626

答え1

使用する場合最新 ksh- 最新バージョンを意味しますksh93。実際に使用できます。ksh93サポートする化合物変数タイプ(C構造体と同じ種類)またはXMLノードツリー。現在、デフォルトではXMLをサポートしていません。それは計画されていると確信していますが、json今はサポートしています。

私はいくつか使用しました無料オンラインコンバーターjsonサンプル出力を得るためのものです。それにもかかわらず、サンプルを少し整理した後(これ存在する</接続プール>ちなみに大文字にしてください)私はそれをすることができます:

print -j queue.services.[@name]

...そして報酬を得る...

GETME

私もこれを行うことができます:

print -j queue.services[1].[@name]

...代わりに...

GETME2

リンクされたコンバージョンサイトで選択する必要があります。タブ区切り邪魔されない空間がたくさん付くのを防ぐためのほかは大丈夫そうです。もちろん、同様の変換を実行するためにローカルで簡単に使用できるツールがあります。

とにかく、私がやったようにクリップボードにコピーしてkshツリーから読むことができます。たとえば、次のようになります。json

read -m json queue <<<"$(xsel -bo)"

この作業が完了すると、次のような構造全体が表示されます。

print -j queue

...印刷...

{
    "batchServices": [
        {
            "@name": "batch1",
            "executor": {
                "@className": "com.abc.xyz.qwer.qweqwewqe.ffdsdfsdfsdfsdf"
            }
        },
        {
            "@name": "batch2",
            "executor": {
                "@className": "com.abc.xyz.qwer.qweqwewqe.zxcsadsad"
            }
        }
    ],
    "configfile": "sample.xml",
    "connectionPools": [
        {
            "driver": "oracle.jdbc.driver.OracleDriver",
            "maxConnections": "10",
            "minConnections": "0",
            "name": "asdasd",
            "password": "$asdasd_PASSWORD",
            "poolUrl": "jdbc:asdsad:asdasdsad",
            "testSql": "select * from abc",
            "url": "$asdasd_URL",
            "userId": "$asdasd_USER"
        }
    ],
    "exceptionsFilterConfigFile": "asdasd.xml",
    "keyInfoConfigFile": "asdasd.xml",
    "services": [
        {
            "@backend": "ABC",
            "@idleTime": "300",
            "@max": "10",
            "@min": "1",
            "@name": "GETME",
            "handlerContainer": {
                "@className": "com.abc.xyz.wqere.abcqwere",
                "handler": {
                    "@className": "com.abc.xyz.qweqweqwe.werwerwerwer"
                }
            },
            "mqListener": {
                "@copyMessageId": "true",
                "@maxExpiry": "500",
                "@minExpiry": "4",
                "@queue": "ABC.getme",
                "@suggExpiry": "30"
            }
        },
        {
            "@backend": "ABC",
            "@idleTime": "300",
            "@max": "10",
            "@min": "1",
            "@name": "GETME2",
            "handlerContainer": {
                "@className": "com.abc.xyz.wqere.abcqwere",
                "handler": {
                    "@className": "com.abc.xyz.qweqweqwe.werwerwerwer"
                }
            },
            "mqListener": {
                "@copyMessageId": "true",
                "@maxExpiry": "500",
                "@minExpiry": "4",
                "@queue": "ABC.getme2",
                "@suggExpiry": "30"
            }
        }
    ]
}

答え2

上記のコメントで述べたように、xmllint次のように使用できます。

xmllint --xpath '//service/[@name="GETME"]' Sample.xml

このオプションは libxml バージョン 20903 以降から使用できます。

xpath構文の入門書はここにあります:http://www.w3schools.com/xpath/xpath_syntax.aspまたはそれ以上の権威あるhttps://www.w3.org/Consortium/Offices/Presentations/XSLT_XPATH/#(23)

答え3

適格:

  1. 読み取り専用権限がないため、XMLパーサーツールは使用できません。

  2. 私のバージョンのxmllintはxpathをサポートしていません。更新できず、読み取り専用です。

  3. xmlstarletがないためインストールできません。

私は他の非伝統的な解決策を見つけることに頼っていました。この awk コマンドは私の要件を満たしています。

awk '
  /<service.*name=/ { f=1 ; m=0 ; res="" }
  f { res = res $0 ORS }
  f && /mqListener queue="ABC.getme2"/ { m=1 }
  /<\/service>/ { f=0 ; if (m) print res $0 }
' Sample.xml

ここで私を助けてくれた@Janisに特に感謝します。入力パラメータがブロックの中央にあるときにxmlブロックを取得するときにawkスコープモードを実装する方法

答え4

とりわけ、grepXMLは正規表現ベースの解析に適した形式ではありません。代わりにXMLパーサーを使用してください。

私のお気に入りのXMLパーサーは、実際にはperl次のようなプログラムです。XML::Twig

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my ($keyword, $filename) = @ARGV;

XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => {
        'service[@name="'.$keyword.'"]' => sub { $_->print }
    }
)->parsefile($filename);

呼び出すと、myscript.pl GETME yourxml一致するすべての項目が印刷されます。 (pretty_print希望の形式に変更してください。)

XML::Twig実際には、いくつかの例のユースケースも一緒にバンドルされているため、たとえばxml_grep必要なタスクをたくさん実行できます。

上記のサンプルXMLの使用推定ソースXMLは実際には次のようになります。これは転置エラーです。

<service
        backend="ABC"
        idleTime="300"
        max="10"
        min="1"
        name="GETME">
      <handlerContainer className="com.abc.xyz.wqere.abcqwere">
        <handler className="com.abc.xyz.qweqweqwe.werwerwerwer" />
      </handlerContainer>
      <mqListener
          copyMessageId="true"
          maxExpiry="500"
          minExpiry="4"
          queue="ABC.getme"
          suggExpiry="30"
      />
    </service>

注:この形式indented_aXML::Twig他の形式を使用できます。これが正規表現と行ベースのXMLマッチングが危険な理由の少なくとも一部です。

関連情報