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,'
')"/>
</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")