Home > Mobile >  Unable to associate or grouping each set of xml attributes in bash script
Unable to associate or grouping each set of xml attributes in bash script

Time:06-13

I have following format xml which has multiple occurrences of same attributes ( name , code and format ).

<?xml version="1.0" encoding="UTF-8"?>
<config>
 <input>
    <pattern>
        <name>ABC</name>
        <code>1234</code>
        <format>txt</format>
    </pattern>
 </input>
 <input>
    <pattern>
        <name>XYZ</name>
        <code>7799</code>
        <format>csv</format>
     </pattern>
 </input>
</config>

I want to parse each of these patterns and construct string like : ABC-1234-txt , XYZ-7799-csv etc... and add this to an array. The idea here is to group each pattern by constructing the string which will further be used. I have tried below command but unable to maintain the grouping :

awk -F'</?name>|</?code>|</?format>' ' { print $2 } ' sample.xml

It simply prints available values of these attributes in xml. As I am not an expert in bash so can anyone please suggest me how to group each pattern in above mentioned format in string.

CodePudding user response:

With bash and xmlstarlet:

mapfile -t array < <(
  xmlstarlet select \
    --text --template --match '//config/input/pattern' \
    --value-of "concat(name,'-',code,'-',format)" -n file.xml
)
declare -p array

Output:

declare -a array=([0]="ABC-1234-txt" [1]="XYZ-7799-csv")

See: help mapfile and xmlstarlet select

CodePudding user response:

with xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space  elements="*"/>
<xsl:template match="pattern">
    <xsl:value-of select="concat(name,'-',code,'-',format,'&#xA;')"/>
</xsl:template>
</xsl:stylesheet>

Apply the transform via xsltproc:

$ xsltproc example.xslt sample.xml
ABC-1234-txt
XYZ-7799-csv

Populate array with xslt output:

$ declare -a my_array 
$ my_array=($(xsltproc example.xslt sample.xml))
$ echo "${my_array[@]}"
ABC-1234-txt XYZ-7799-csv
$ echo "${my_array[1]}"
XYZ-7799-csv

CodePudding user response:

Using xq (jq syntax) (to get xq --> pip install yq)

$ readarray -t myArray < <(xq -r '.config.input[].pattern | "\(.name)-\(.code)-\(.format)"' input.xml)
$ declare -p myArray
declare -a myArray=([0]="ABC-1234-txt" [1]="XYZ-7799-csv")

Using awk

$ readarray -t myArray < <(awk -F"</?(name|code|format)>" '/<name>/{n=$2;getline;c=$2;getline;print n"-"c"-"$2}' <(xmllint --format input.xml))
$ declare -p myArray
declare -a myArray=([0]="ABC-1234-txt" [1]="XYZ-7799-csv")

Using grep & sed

$ readarray -t myArray < <(xmllint --format input.xml|grep -E '<name>|<code>|<format>'|sed -E 'N;N;s/\n/-/g; s/<\/?\w >//g; s/ //g')
$ declare -p myArray
declare -a myArray=([0]="ABC-1234-txt" [1]="XYZ-7799-csv")

Using rdom function (source stackowerflow)

$ rdom () { local IFS=\> ; read -d \< E C ;}
$ myArray=()
$ while rdom; do
>   [ "$E" = "name" ] && name=$C
>   [ "$E" = "code" ] && code=$C
>   [ "$E" = "format" ] && { format="$C"; myArray =("$name-$code-$format"); }
> done < input.xml

$ declare -p myArray

declare -a myArray=([0]="ABC-1234-txt" [1]="XYZ-7799-csv")
  • Related