Advertisement
Guest User

Untitled

a guest
Jul 20th, 2019
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.73 KB | None | 0 0
  1. #!/usr/bin/env bash
  2.  
  3. # Read XML from STDIN
  4. read_xml()
  5. {
  6. # concatenate lines
  7. local XML
  8.  
  9. while read -r
  10. do
  11. XML=$XML${REPLY//$'\t'/ }
  12. done
  13.  
  14. # parse XML string
  15. local TAG NAME DIR ARG VALUE
  16. local CONTENT='' INDEX=0
  17.  
  18. while [[ $XML == *'<'* ]]
  19. do
  20. TAG=${XML#*<}
  21. TAG=${TAG%%>*}
  22. NAME=${TAG%% *}
  23.  
  24. # skip comments
  25. case $NAME in
  26. '!--'*)
  27. XML=${XML#*-->}
  28. continue
  29. ;;
  30. esac
  31.  
  32. XML=${XML#*>}
  33.  
  34. # skip special tags
  35. case ${NAME:0:1} in
  36. '/')
  37. echo $CONTENT > =cdata
  38. CONTENT=
  39. cd ..
  40. continue
  41. ;;
  42. '?'|'!')
  43. continue
  44. ;;
  45. esac
  46.  
  47. # skip empty tags
  48. [[ $NAME == *'/' ]] && continue
  49.  
  50. DIR=$NAME-$(( INDEX++ ))
  51. mkdir "$DIR"
  52. cd "$DIR" || return 1
  53.  
  54. if [[ $TAG == *' '* ]]
  55. then
  56. # eval is required to support quoting of values
  57. eval "for ARG in ${TAG#* }; do echo \"\$ARG\"; done" |
  58. while read -r ARG
  59. do
  60. [ "$ARG" == '/' ] && break
  61.  
  62. if [[ $ARG == *'='* ]]
  63. then
  64. VALUE=${ARG#*=}
  65. VALUE=${VALUE%/}
  66.  
  67. # remove quotes
  68. case ${VALUE:0:1} in
  69. '"')
  70. VALUE=${VALUE#\"}
  71. VALUE=${VALUE%\"}
  72. ;;
  73. "'")
  74. VALUE=${VALUE#\'}
  75. VALUE=${VALUE%\'}
  76. ;;
  77. esac
  78.  
  79. echo "$VALUE" > "${ARG%%=*}"
  80. else
  81. touch "$ARG"
  82. fi
  83. done
  84. fi
  85.  
  86. if [[ $TAG == *'/' ]]
  87. then
  88. CONTENT=
  89. cd ..
  90. continue
  91. fi
  92.  
  93. CONTENT=$CONTENT${XML%%<*}
  94. done
  95. }
  96.  
  97. # Find file KEY and check if contents match VALUE
  98. #
  99. # @param 1 - KEY=VALUE pair
  100. find_xml_arguments()
  101. {
  102. local ARG
  103.  
  104. for ARG in ${1//\&/ }
  105. do
  106. # skip arguments without a value
  107. [[ $ARG == *=* ]] || continue
  108.  
  109. # try to match argument value
  110. [[ $(< "${ARG%%=*}") == "${ARG#*=}" ]] || return 1
  111. done &>/dev/null
  112. }
  113.  
  114. # Print matching XML node
  115. #
  116. # @param 1 - XML path
  117. find_xml_path()
  118. {
  119. local NODE=${1%%/*}
  120. local DIR
  121.  
  122. for DIR in ${NODE%%\?*}-*
  123. do
  124. cd "$DIR" &>/dev/null || break
  125.  
  126. if [[ "$NODE" == *'?'* ]]
  127. then
  128. find_xml_arguments "${NODE#*\?}" || {
  129. cd ..
  130. continue
  131. }
  132. fi
  133.  
  134. # either all arguments were found or no
  135. # arguments were specified for this node
  136. if [ "$NODE" == "${1%/}" ]
  137. then
  138. pwd
  139. else
  140. find_xml_path "${1#*/}"
  141. fi
  142.  
  143. cd ..
  144. done
  145. }
  146.  
  147. # Print matching XML nodes
  148. #
  149. # @param ... - XML paths
  150. find_xml_paths()
  151. {
  152. local IN OUT LAST
  153.  
  154. for IN
  155. do
  156. LAST=${IN##*/}
  157.  
  158. for OUT in $(find_xml_path $IN)
  159. do
  160. if [[ $LAST == *\?* ]] && [[ $LAST != *=* ]]
  161. then
  162. cat "$OUT/${IN##*\?}"
  163. else
  164. cat "$OUT/=cdata"
  165. fi
  166. done
  167. done
  168. }
  169.  
  170. # Read XML from STDIN and find a node
  171. #
  172. # @param ... - XML path
  173. xml()
  174. {
  175. local XML_CACHE
  176. XML_CACHE=$(mktemp -d "${0##*/}.XXXXXXXXXX")
  177.  
  178. (cd "$XML_CACHE" && read_xml && find_xml_paths "$@")
  179.  
  180. rm -rf "$XML_CACHE"
  181. }
  182.  
  183. if [ "${BASH_SOURCE[0]}" == "$0" ]
  184. then
  185. if (( $# < 1 ))
  186. then
  187. echo "usage: ${0##*/} PATH/TO?ARGUMENT=VALUE/NODE..."
  188. else
  189. xml "$@"
  190. fi
  191. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement