Извлечение данных из файла XML с помощью команд оболочки - PullRequest
0 голосов
/ 04 января 2019

У меня есть XML с содержимым ниже, и мой вопрос заключается в том, как извлечь имя пользователя, значения пароля из тега ресурса, здесь нам нужно исключить закомментированный тег ресурса и извлечь значения из некомментированного тега ресурса с помощью сценария оболочки.Я пытался, но он выбирал значения из последнего тега.Может кто-нибудь помочь мне, как удалить теги комментариев и получить значения из XML.

<?xml version='1.0' encoding='utf-8'?>
<!-- The contents of this file will be loaded for each web application -->
<!--
 <Resource name="jdbcSource" auth="Container"
type="javax.sql.DataSource"
 username="demo"
    password="test"
        driverClassName="driverclassname"
        url="driver@host"
    maxActive="20"
    maxIdle="10"
     />

-->

<Resource auth="Container"
driverClassName="driverclassname" maxActive="100" maxIdle="30" maxWait="10000"
name="jdbcSource" password="test" type="javax.sql.DataSource"
url="driver@host"
username="demo"/>

</Context>

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Во-первых, мой ответ предполагает, что у вас есть действительно правильно сформированный исходный XML.Предоставленный вами пример кода не является XML, так как он не имеет открываемого корневого элемента, а именно <Context> - но я все равно предположу, что он есть.


Bashфункции сами по себе не очень хорошо подходят для разбора XML

В этом Bash FAQ указано следующее:

Не пытаться [извлечь данные из файла XML] с помощью , , и т. д. (это приводит к нежелательным результатам )

Если необходимо использоватьЗатем сценарий оболочки использует специальный инструмент командной строки для XML, такой как XMLStarlet (есть и другие подобные инструменты).См. Информацию о загрузке здесь - если у вас еще не установлен XML Starlet.

Решение:

Используя XML Starlet, вы можете запустить следующие команды:

uname=$(xml sel -t -v "/Context/Resource/@username" path/to/file.xml)
pword=$(xml sel -t -v "/Context/Resource/@password" path/to/file.xml)

echo "$uname $pword" # --> demo test

Пояснение

  • uname=$(...)

    Здесь мы используем Подстановка команд назначить вывод команды XML Startlet переменной с именем uname (т. е. имя пользователя).

  • xml sel -t -v "/Context/Resource/@username"

    ThisКоманда разбивается следующим образом:

    • xml - вызвать команду XML Starlet.
    • sel - выбрать данные илизапросить XML-документ (ы).
    • -t - опция шаблона.
    • -v - вывести значение выражения XPATH.
    • "/Context/Resource/@username" - выражение для выбора значения атрибута username тега / элемента Resource.
  • path/to/file.xml

    Эта часть должна быть замененаced с реальным путем к вашему файлу .xml.

Аналогично, мы используем аналогичную команду для получения значения атрибута password, посредством чего мы назначаем вывод командыв переменную с именем pword и измените выражение XPATH.


Редактировать 1: более эффективная команда

Согласно Чарльз Даффи * первый комментарий ниже ... вы также можете более эффективно извлечь оба значения атрибута, используя следующую команду:

{ IFS= read -r uname && IFS= read -r pword; } < <(xml sel -t -v "/Context/Resource/@username" -n -v "/Context/Resource/@password" path/to/file.xml)

echo "$uname $pword" # --> demo test

Основное преимущество заключается в том, что исходный XML-файл читается только один раз.


Редактировать 2: Использование XML Starlet для генерации шаблона XSLT, который затем можно запустить в любой системе с xsltproc, включая хосты, на которых не установлен XML Starlet:

Согласно Charles DuffyВторой комментарий ниже ...

Также возможно использовать XML Starlet для генерации шаблона , который получен из запроса XML Starlet, показанного ранее.Созданный файл .xsl может быть запущен в любой системе, в которой есть (включая хосты, на которых не установлен XML Starlet).

Следующие шаги демонстрируют, как этого добиться:

  1. Сначала выполните следующую команду XML Starlet для создания файла .xsl:

    xml sel -C -t -v "/Context/Resource/@username" -n -v "/Context/Resource/@password" path/to/file.xml > path/to/resultant/my-template.xsl
    

    Эта команда очень похожа на ранее показанную команду XML Starlet.Существенные различия:

    • Дополнительная опция -C между sel и -t
    • Оператор перенаправления > ипуть к файлу.Здесь указывается место, в котором следует сохранить выходные данные (т. Е. Сгенерированный шаблон / таблица стилей XSLT).

      Примечание необходимо изменить часть path/to/resultant/my-template.xsl при необходимости.

    Содержимое сгенерированной таблицы стилей XSLT будет выглядеть примерно так:

    my-template.xsl

    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
      <xsl:output omit-xml-declaration="yes" indent="no"/>
      <xsl:template match="/">
        <xsl:call-template name="value-of-template">
          <xsl:with-param name="select" select="/Context/Resource/@username"/>
        </xsl:call-template>
        <xsl:value-of select="'&#10;'"/>
        <xsl:call-template name="value-of-template">
          <xsl:with-param name="select" select="/Context/Resource/@password"/>
        </xsl:call-template>
      </xsl:template>
      <xsl:template name="value-of-template">
        <xsl:param name="select"/>
        <xsl:value-of select="$select"/>
        <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
          <xsl:value-of select="'&#10;'"/>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    
  2. Далее выполните следующую команду, которая использует для преобразованияисходный файл .xml.Это в конечном итоге присваивает результат преобразования двум переменным, то есть uname и pword:

    { IFS= read -r uname && IFS= read -r pword; } < <(xsltproc path/to/resultant/my-template.xsl path/to/file.xml)
    
    echo "$uname $pword" # --> demo test
    

    Примечание детали, обозначенные path/to/resultant/my-template.xsl и path/to/file.xml, должны быть при необходимости изменены.


0 голосов
/ 04 января 2019

с одним вкладышем perl

perl -n0777E '
    # remove comments
    s/<!--.*?-->//gs;

    # match username and password with lookaheads and display in custom way
    say "user:$1\tpass:$2" while /<Resource(?=[^>]*\susername="([^"]*)")(?=[^>]*\spassword="([^"]*)")[^>]*>/g
' < file.xml
...