Как grep блок xml в файле xml с помощью ключевого слова

У меня есть файл Sample.xml, в котором содержится множество сервисов, и структура выглядит так:

ПРОБЛЕМА: ВХОД: НАЗВАНИЕ ОЧЕРЕДИ ВЫХОД: БЛОК СЛУЖБЫ

образец ВВОД: 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>

Мне нужно grep блок xml следующим образом:

 <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. . . 

Я попробовал ответ ниже

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

и

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

и

xmlstarlet sel -t -v "/services/service[@name='GETME']/mqListener/@queue" Sample.xml

но не получилось

Вот результат:

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

person Philip Morris    schedule 02.06.2015    source источник
comment
... Итак, у вас нет xmllint с доступной поддержкой XPath, у вас нет xmlstarlet - нам действительно нужно знать, что у вас есть (может быть, последний Python? ) прежде чем мы могли бы быть гораздо больше помочь.   -  person Charles Duffy    schedule 02.06.2015
comment
Я видел парсинг XML в awk и sed. Можно ли это сделать с помощью этих команд? Я действительно не уверен в том, что у меня есть, что может быть полезно. xmllint и xmlstarlet были лучшим выбором - stackoverflow.com/questions/15879169/   -  person Philip Morris    schedule 02.06.2015
comment
Нет, awk и sed не подходят для задачи. См. также stackoverflow.com/questions/1732348/ - он начинается с (точных) утверждений о теории языка. Конечно, awk более выразителен, чем BRE, и теоретически можно было бы написать синтаксический анализатор XML в awk, но, как и любой другой синтаксический анализатор XML, это был бы крупный проект для создания и тестирования; большие библиотеки манипулирования XML требуют усилий, измеряемых в человеко-годах, для достижения полного соответствия.   -  person Charles Duffy    schedule 02.06.2015
comment
Возможно, вы сможете создать что-то с помощью awk, которое будет работать какое-то время, но добавьте пространства имен, комментарии, разделы CDATA, и вы начнете быстро находить ошибки. Используйте правильный синтаксический анализатор XML, и вы получите то, что на самом деле гарантировано, чтобы делать правильные вещи.   -  person Charles Duffy    schedule 02.06.2015
comment
Тем не менее, любая современная платформа будет включать в себя интерпретатор Python с включенным надлежащим парсером XML. Вызов Python из оболочки на самом деле не так уж и сложен.   -  person Charles Duffy    schedule 02.06.2015
comment
Почему бы вам не взглянуть на один из ответов, уже показывающих вам, как в одном из многих, многих дубликатов этого вопроса?   -  person Charles Duffy    schedule 02.06.2015
comment
Кстати, у вас установлен xsltproc?   -  person Charles Duffy    schedule 02.06.2015
comment
-ksh: xsltproc: не найден [Нет такого файла или каталога]   -  person Philip Morris    schedule 02.06.2015
comment
Я немного отчаялся и сделал это: awk '/‹service.*name=GETME.*/,/‹\/service›/' Sample.xml, но мне нужно имя очереди в качестве ввода, а не имя службы   -  person Philip Morris    schedule 02.06.2015
comment
Вы так и не сказали мне, какая версия Python установлена. Я хотел бы знать это, чтобы не тратить время на написание реализации с помощью Python.   -  person Charles Duffy    schedule 02.06.2015
comment
Давайте продолжим обсуждение в чате.   -  person Charles Duffy    schedule 02.06.2015


Ответы (2)


Команда почти правильная, вам нужно только исправить выражение XPATH:

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

Однако вы должны проверить, действительно ли ваш xmllint поддерживает XPATH:

$ xmllint --version
xmllint: using libxml version 20902
   compiled with: Threads Tree Output Push Reader Patterns Writer
   SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer
   XInclude Iconv ISO8859X Unicode Regexps Automata Expr Schemas
   Schematron Modules Debug Zlib Lzma 
person dlask    schedule 02.06.2015
comment
Какая разница? В исходном примере правильный порядок параметров и файлов. - person dlask; 02.06.2015
comment
Я не знаю. Я добавил трассировку стека, и кажется, что xpath там нет - person Philip Morris; 02.06.2015
comment
xpath отсутствует в рекомендуемом использовании в соответствии с трассировкой стека - person Philip Morris; 02.06.2015
comment
Возможно старая версия xmlint. Кстати, предоставленный текст не является трассировкой стека, см. en.wikipedia.org/wiki/Stack_trace - person dlask; 02.06.2015
comment
xmlint: использование libxml версии 20626 - person Philip Morris; 02.06.2015
comment
@PhilipMorris, версия xmllint имеет значение, а не версия libxml, с которой она связана. Все версии libxml поддерживают xpath. - person Charles Duffy; 02.06.2015
comment
у тебя 20902 а у меня 20626 - person Philip Morris; 02.06.2015
comment
@PhilipMorris, да, это версии libxml2, с которыми скомпилированы соответствующие сборки xmllint, но версия libxml2 не совпадает с версией xmllint. - person Charles Duffy; 02.06.2015

Альтернативным инструментом для этой цели является XMLStarlet:

xmlstarlet sel -t -c '//service[@name="GETME"]' -n <Sample.xml

Между прочим, xmlstarlet также может выводить XSLT, который вы можете применить с помощью xsltproc и, таким образом, в системах без установленного xmlstarlet. В таком случае:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="no"/>
  <xsl:template match="/">
    <xsl:copy-of select="//service[@name=&quot;GETME&quot;]"/>
    <xsl:value-of select="'&#10;'"/>
  </xsl:template>
</xsl:stylesheet>
person Charles Duffy    schedule 02.06.2015
comment
-ksh: xmlstarlet: не найден [Нет такого файла или каталога]. А я только в режиме чтения =( - person Philip Morris; 02.06.2015
comment
Очевидно, что вам нужно установить инструмент, прежде чем вы сможете его использовать. - person Charles Duffy; 02.06.2015
comment
У меня нет разрешения на установку инструмента. Есть ли другие способы? - person Philip Morris; 02.06.2015