web-dev-qa-db-fra.com

Comment analyser XML dans Bash?

Idéalement, ce que j'aimerais pouvoir faire, c'est:

cat xhtmlfile.xhtml |
getElementViaXPath --path='/html/head/title' |
sed -e 's%(^<title>|</title>$)%%g' > titleOfXHTMLPage.txt
126
asdfasdfasdf

C’est vraiment juste une explication de la réponse de Yuzem , mais j’ai eu l'impression que cela ne devrait pas être beaucoup édité, et que les commentaires ne permettent pas le formatage, alors ...

rdom () { local IFS=\> ; read -d \< E C ;}

Appelons cela "read_dom" au lieu de "rdom", l'espace un peu et utilisons des variables plus longues:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
}

Bon alors il définit une fonction appelée read_dom. La première ligne rend IFS (le séparateur de champ de saisie) local à cette fonction et le remplace par>. Cela signifie que lorsque vous lisez des données au lieu d'être automatiquement divisées sur des espaces, des tabulations ou des nouvelles lignes, elles sont scindées sur '>'. La ligne suivante indique de lire les entrées à partir de stdin et, au lieu de s'arrêter à une nouvelle ligne, arrêtez-vous lorsque vous voyez un caractère '<' (l'indicateur -d pour le suppresseur). Ce qui est lu est ensuite divisé en utilisant l’IFS et affecté à la variable ENTITY et au contenu. Alors prenez ce qui suit:

<tag>value</tag>

Le premier appel à read_dom obtient une chaîne vide (puisque '<' est le premier caractère). Cela est divisé par IFS en juste '', car il n'y a pas de caractère '>'. Read attribue ensuite une chaîne vide aux deux variables. Le deuxième appel obtient la chaîne 'tag> value'. Celle-ci est ensuite divisée par l’IFS en deux balises "tag" et "value". Lire assigne ensuite les variables telles que: ENTITY=tag et CONTENT=value. Le troisième appel obtient la chaîne '/ tag>'. Celui-ci est divisé par l’IFS entre les deux champs '/ tag' et ''. Lire assigne ensuite les variables telles que: ENTITY=/tag et CONTENT=. Le quatrième appel retournera un statut différent de zéro car nous avons atteint la fin du fichier.

Maintenant sa boucle while nettoyée un peu pour correspondre à ce qui précède:

while read_dom; do
    if [[ $ENTITY = "title" ]]; then
        echo $CONTENT
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt

La première ligne indique simplement: "pendant que la fonction read_dom renvoie un état égal à zéro, procédez comme suit". La deuxième ligne vérifie si l'entité que nous venons de voir est "title". La ligne suivante rappelle le contenu de la balise. Les quatre lignes sortent. Si ce n'était pas l'entité du titre, la boucle se répète à la sixième ligne. Nous redirigeons "xhtmlfile.xhtml" en entrée standard (pour la fonction read_dom) et redirigeons la sortie standard en "titleOfXHTMLPage.txt" (l'écho de la boucle précédente).

Maintenant, étant donné ce qui suit (similaire à ce que vous obtenez en listant un seau sur S3) pour input.xml:

<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name>sth-items</Name>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>[email protected]</Key>
    <LastModified>2011-07-25T22:23:04.000Z</LastModified>
    <ETag>&quot;0032a28286680abee71aed5d059c6a09&quot;</ETag>
    <Size>1785</Size>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
</ListBucketResult>

et la boucle suivante:

while read_dom; do
    echo "$ENTITY => $CONTENT"
done < input.xml

Tu devrais obtenir:

 => 
ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/" => 
Name => sth-items
/Name => 
IsTruncated => false
/IsTruncated => 
Contents => 
Key => [email protected]
/Key => 
LastModified => 2011-07-25T22:23:04.000Z
/LastModified => 
ETag => &quot;0032a28286680abee71aed5d059c6a09&quot;
/ETag => 
Size => 1785
/Size => 
StorageClass => STANDARD
/StorageClass => 
/Contents => 

Donc, si nous écrivions une boucle while comme celle de Yuzem:

while read_dom; do
    if [[ $ENTITY = "Key" ]] ; then
        echo $CONTENT
    fi
done < input.xml

Nous obtiendrions une liste de tous les fichiers du compartiment S3.

EDIT Si pour quelque raison que ce soit local IFS=\> ne fonctionne pas pour vous et que vous le définissez globalement, vous devez le réinitialiser à la fin de la fonction comme:

read_dom () {
    ORIGINAL_IFS=$IFS
    IFS=\>
    read -d \< ENTITY CONTENT
    IFS=$ORIGINAL_IFS
}

Sinon, toute ligne qui se divise plus tard dans le script sera perturbée.

EDIT 2 Pour séparer les paires nom/valeur d'attribut, vous pouvez augmenter le read_dom() comme ceci:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local ret=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $ret
}

Ensuite, écrivez votre fonction pour analyser et obtenir les données que vous voulez comme ceci:

parse_dom () {
    if [[ $TAG_NAME = "foo" ]] ; then
        eval local $ATTRIBUTES
        echo "foo size is: $size"
    Elif [[ $TAG_NAME = "bar" ]] ; then
        eval local $ATTRIBUTES
        echo "bar type is: $type"
    fi
}

Ensuite, pendant que vous read_dom appelez parse_dom:

while read_dom; do
    parse_dom
done

Ensuite, étant donné l'exemple de balisage suivant:

<example>
  <bar size="bar_size" type="metal">bars content</bar>
  <foo size="1789" type="unknown">foos content</foo>
</example>

Vous devriez obtenir cette sortie:

$ cat example.xml | ./bash_xml.sh 
bar type is: metal
foo size is: 1789

EDIT 3 Un autre tilisateur dit qu'ils avaient des problèmes avec cela dans FreeBSD et a suggéré de sauvegarder le statut de sortie de la lecture et de le retourner à la fin de read_dom comme:

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local RET=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $RET
}

Je ne vois aucune raison pour que cela ne fonctionne pas

142
chad

Vous pouvez le faire très facilement en utilisant seulement bash. Il suffit d'ajouter cette fonction:

rdom () { local IFS=\> ; read -d \< E C ;}

Vous pouvez maintenant utiliser rdom comme read mais pour les documents HTML. Lorsque appelé, rdom assignera l'élément à la variable E et le contenu à la variable C.

Par exemple, pour faire ce que vous vouliez faire:

while rdom; do
    if [[ $E = title ]]; then
        echo $C
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt
59
Yuzem

Les outils de ligne de commande pouvant être appelés à partir de scripts Shell incluent:

  • 4xpath - Enveloppe de ligne de commande autour du paquet 4Suite de Python
  • XMLStarlet
  • xpath - wrapper en ligne de commande autour de la bibliothèque XPath de Perl
  • Xidel - Fonctionne avec les URL ainsi que les fichiers. Fonctionne également avec JSON

J'utilise également xmllint et xsltproc avec de petits scripts de transformation XSL pour effectuer un traitement XML à partir de la ligne de commande ou dans des scripts Shell.

54
Nat

Vous pouvez utiliser l'utilitaire xpath. Il est installé avec le paquet Perl XML-XPath.

Usage:

/usr/bin/xpath [filename] query

ou XMLStarlet . Pour l'installer sur opensuse, utilisez:

Sudo zypper install xmlstarlet

ou essayez cnf xml sur d'autres plateformes.

22
Grisha

C'est suffisant ...

xpath xhtmlfile.xhtml '/html/head/title/text()' > titleOfXHTMLPage.txt
8
teknopaul

Vérifier XML2 de http://www.ofb.net/~egnor/xml2/ qui convertit XML en une ligne format orienté.

5
simon04

à partir de la réponse de chad, voici la solution de travail COMPLETE pour analyser le langage UML, avec une gestion correcte des commentaires, avec seulement 2 petites fonctions (plus de 2 mais vous pouvez les mélanger toutes). Je ne dis pas que celui de chad ne fonctionnait pas du tout, mais il y avait trop de problèmes avec les fichiers XML mal formatés: vous devez donc être un peu plus délicat à gérer les commentaires et les espaces mal placés/CR/TAB/etc.

Le but de cette réponse est de donner des fonctions clés en main ready-2-use, à tous ceux qui ont besoin d'analyser du langage UML sans utiliser des outils complexes utilisant Perl, python ou autre chose. Quant à moi, je ne peux pas installer cpan, ni les modules Perl pour l'ancien système d'exploitation sur lequel je travaille, et python n'est pas disponible.

Premièrement, une définition des mots UML utilisés dans ce post:

<!-- comment... -->
<tag attribute="value">content...</tag>

EDIT: fonctions mises à jour, avec handle de:

  • Websphere xml (attributs xmi et xmlns)
  • doit avoir un terminal compatible avec 256 couleurs
  • 24 nuances de gris
  • compatibilité ajoutée pour IBM AIX bash 3.2.16 (1)

Les fonctions, en premier lieu, sont xml_read_dom, appelé récursivement par xml_read:

xml_read_dom() {
# https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash
local ENTITY IFS=\>
if $ITSACOMMENT; then
  read -d \< COMMENTS
  COMMENTS="$(rtrim "${COMMENTS}")"
  return 0
else
  read -d \< ENTITY CONTENT
  CR=$?
  [ "x${ENTITY:0:1}x" == "x/x" ] && return 0
  TAG_NAME=${ENTITY%%[[:space:]]*}
  [ "x${TAG_NAME}x" == "x?xmlx" ] && TAG_NAME=xml
  TAG_NAME=${TAG_NAME%%:*}
  ATTRIBUTES=${ENTITY#*[[:space:]]}
  ATTRIBUTES="${ATTRIBUTES//xmi:/}"
  ATTRIBUTES="${ATTRIBUTES//xmlns:/}"
fi

# when comments sticks to !-- :
[ "x${TAG_NAME:0:3}x" == "x!--x" ] && COMMENTS="${TAG_NAME:3} ${ATTRIBUTES}" && ITSACOMMENT=true && return 0

# http://tldp.org/LDP/abs/html/string-manipulation.html
# INFO: oh wait it doesn't work on IBM AIX bash 3.2.16(1):
# [ "x${ATTRIBUTES:(-1):1}x" == "x/x" -o "x${ATTRIBUTES:(-1):1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:(-1)}"
[ "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x/x" -o "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:${#ATTRIBUTES} -1}"
return $CR
}

et le second:

xml_read() {
# https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash
ITSACOMMENT=false
local MULTIPLE_ATTR LIGHT FORCE_PRINT XAPPLY XCOMMAND XATTRIBUTE GETCONTENT fileXml tag attributes attribute tag2print TAGPRINTED attribute2print XAPPLIED_COLOR PROSTPROCESS USAGE
local TMP LOG LOGG
LIGHT=false
FORCE_PRINT=false
XAPPLY=false
MULTIPLE_ATTR=false
XAPPLIED_COLOR=g
TAGPRINTED=false
GETCONTENT=false
PROSTPROCESS=cat
Debug=${Debug:-false}
TMP=/tmp/xml_read.$RANDOM
USAGE="${C}${FUNCNAME}${c} [-cdlp] [-x command <-a attribute>] <file.xml> [tag | \"any\"] [attributes .. | \"content\"]
${nn[2]}  -c = NOCOLOR${END}
${nn[2]}  -d = Debug${END}
${nn[2]}  -l = LIGHT (no \"attribute=\" printed)${END}
${nn[2]}  -p = FORCE PRINT (when no attributes given)${END}
${nn[2]}  -x = apply a command on an attribute and print the result instead of the former value, in green color${END}
${nn[1]}  (no attribute given will load their values into your Shell; use '-p' to print them as well)${END}"

! (($#)) && echo2 "$USAGE" && return 99
(( $# < 2 )) && ERROR nbaram 2 0 && return 99
# getopts:
while getopts :cdlpx:a: _OPT 2>/dev/null
do
{
  case ${_OPT} in
    c) PROSTPROCESS="${DECOLORIZE}" ;;
    d) local Debug=true ;;
    l) LIGHT=true; XAPPLIED_COLOR=END ;;
    p) FORCE_PRINT=true ;;
    x) XAPPLY=true; XCOMMAND="${OPTARG}" ;;
    a) XATTRIBUTE="${OPTARG}" ;;
    *) _NOARGS="${_NOARGS}${_NOARGS+, }-${OPTARG}" ;;
  esac
}
done
shift $((OPTIND - 1))
unset _OPT OPTARG OPTIND
[ "X${_NOARGS}" != "X" ] && ERROR param "${_NOARGS}" 0

fileXml=$1
tag=$2
(( $# > 2 )) && shift 2 && attributes=$*
(( $# > 1 )) && MULTIPLE_ATTR=true

[ -d "${fileXml}" -o ! -s "${fileXml}" ] && ERROR empty "${fileXml}" 0 && return 1
$XAPPLY && $MULTIPLE_ATTR && [ -z "${XATTRIBUTE}" ] && ERROR param "-x command " 0 && return 2
# nb attributes == 1 because $MULTIPLE_ATTR is false
[ "${attributes}" == "content" ] && GETCONTENT=true

while xml_read_dom; do
  # (( CR != 0 )) && break
  (( PIPESTATUS[1] != 0 )) && break

  if $ITSACOMMENT; then
    # oh wait it doesn't work on IBM AIX bash 3.2.16(1):
    # if [ "x${COMMENTS:(-2):2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:(-2)}" && ITSACOMMENT=false
    # Elif [ "x${COMMENTS:(-3):3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:(-3)}" && ITSACOMMENT=false
    if [ "x${COMMENTS:${#COMMENTS} - 2:2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 2}" && ITSACOMMENT=false
    Elif [ "x${COMMENTS:${#COMMENTS} - 3:3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 3}" && ITSACOMMENT=false
    fi
    $Debug && echo2 "${N}${COMMENTS}${END}"
  Elif test "${TAG_NAME}"; then
    if [ "x${TAG_NAME}x" == "x${tag}x" -o "x${tag}x" == "xanyx" ]; then
      if $GETCONTENT; then
        CONTENT="$(trim "${CONTENT}")"
        test ${CONTENT} && echo "${CONTENT}"
      else
        # eval local $ATTRIBUTES => eval test "\"\$${attribute}\"" will be true for matching attributes
        eval local $ATTRIBUTES
        $Debug && (echo2 "${m}${TAG_NAME}: ${M}$ATTRIBUTES${END}"; test ${CONTENT} && echo2 "${m}CONTENT=${M}$CONTENT${END}")
        if test "${attributes}"; then
          if $MULTIPLE_ATTR; then
            # we don't print "tag: attr=x ..." for a tag passed as argument: it's usefull only for "any" tags so then we print the matching tags found
            ! $LIGHT && [ "x${tag}x" == "xanyx" ] && tag2print="${g6}${TAG_NAME}: "
            for attribute in ${attributes}; do
              ! $LIGHT && attribute2print="${g10}${attribute}${g6}=${g14}"
              if eval test "\"\$${attribute}\""; then
                test "${tag2print}" && ${print} "${tag2print}"
                TAGPRINTED=true; unset tag2print
                if [ "$XAPPLY" == "true" -a "${attribute}" == "${XATTRIBUTE}" ]; then
                  eval ${print} "%s%s\ " "\${attribute2print}" "\${${XAPPLIED_COLOR}}\"\$(\$XCOMMAND \$${attribute})\"\${END}" && eval unset ${attribute}
                else
                  eval ${print} "%s%s\ " "\${attribute2print}" "\"\$${attribute}\"" && eval unset ${attribute}
                fi
              fi
            done
            # this trick prints a CR only if attributes have been printed durint the loop:
            $TAGPRINTED && ${print} "\n" && TAGPRINTED=false
          else
            if eval test "\"\$${attributes}\""; then
              if $XAPPLY; then
                eval echo "\${g}\$(\$XCOMMAND \$${attributes})" && eval unset ${attributes}
              else
                eval echo "\$${attributes}" && eval unset ${attributes}
              fi
            fi
          fi
        else
          echo eval $ATTRIBUTES >>$TMP
        fi
      fi
    fi
  fi
  unset CR TAG_NAME ATTRIBUTES CONTENT COMMENTS
done < "${fileXml}" | ${PROSTPROCESS}
# http://mywiki.wooledge.org/BashFAQ/024
# INFO: I set variables in a "while loop" that's in a pipeline. Why do they disappear? workaround:
if [ -s "$TMP" ]; then
  $FORCE_PRINT && ! $LIGHT && cat $TMP
  # $FORCE_PRINT && $LIGHT && Perl -pe 's/[[:space:]].*?=/ /g' $TMP
  $FORCE_PRINT && $LIGHT && sed -r 's/[^\"]*([\"][^\"]*[\"][,]?)[^\"]*/\1 /g' $TMP
  . $TMP
  rm -f $TMP
fi
unset ITSACOMMENT
}

et enfin, les fonctions rtrim, trim et echo2 (to stderr):

rtrim() {
local var=$@
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
trim() {
local var=$@
var="${var#"${var%%[![:space:]]*}"}"   # remove leading whitespace characters
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
echo2() { echo -e "$@" 1>&2; }

Colorisation:

oh, et vous aurez besoin de quelques variables dynamiques de colorisation soignées pour être définies au début et exportées aussi:

set -a
TERM=xterm-256color
case ${UNAME} in
AIX|SunOS)
  M=$(${print} '\033[1;35m')
  m=$(${print} '\033[0;35m')
  END=$(${print} '\033[0m')
;;
*)
  m=$(tput setaf 5)
  M=$(tput setaf 13)
  # END=$(tput sgr0)          # issue on Linux: it can produces ^[(B instead of ^[[0m, more likely when using screenrc
  END=$(${print} '\033[0m')
;;
esac
# 24 shades of grey:
for i in $(seq 0 23); do eval g$i="$(${print} \"\\033\[38\;5\;$((232 + i))m\")" ; done
# another way of having an array of 5 shades of grey:
declare -a colorNums=(238 240 243 248 254)
for num in 0 1 2 3 4; do nn[$num]=$(${print} "\033[38;5;${colorNums[$num]}m"); NN[$num]=$(${print} "\033[48;5;${colorNums[$num]}m"); done
# piped decolorization:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

Comment charger tout ça?

Soit vous savez créer des fonctions et les charger via FPATH (ksh) ou une émulation de FPATH (bash)

Sinon, copiez/collez tout sur la ligne de commande.

Comment ça marche:

xml_read [-cdlp] [-x command <-a attribute>] <file.xml> [tag | "any"] [attributes .. | "content"]
  -c = NOCOLOR
  -d = Debug
  -l = LIGHT (no \"attribute=\" printed)
  -p = FORCE PRINT (when no attributes given)
  -x = apply a command on an attribute and print the result instead of the former value, in green color
  (no attribute given will load their values into your Shell as $ATTRIBUTE=value; use '-p' to print them as well)

xml_read server.xml title content     # print content between <title></title>
xml_read server.xml Connector port    # print all port values from Connector tags
xml_read server.xml any port          # print all port values from any tags

En mode débogage (-d), les commentaires et les attributs analysés sont imprimés sur stderr.

5
scavenger

Un autre outil en ligne de commande est mon nouveau Xidel . Il prend également en charge XPath 2 et XQuery, contrairement à xpath/xmlstarlet déjà mentionné.

Le titre peut se lire comme:

xidel xhtmlfile.xhtml -e /html/head/title > titleOfXHTMLPage.txt

Et il a également une fonctionnalité intéressante pour exporter plusieurs variables vers bash. Par exemple

eval $(xidel xhtmlfile.xhtml -e 'title := //title, imgcount := count(//img)' --output-format bash )

définit $title sur le titre et $imgcount sur le nombre d'images du fichier, ce qui devrait être aussi souple que son analyse directe en bash.

4
BeniBela

Je ne connais aucun outil d'analyse syntaxique Shell pur. Vous aurez donc probablement besoin d'un outil écrit dans une autre langue.

Mon module XML :: Twig Perl est livré avec un tel outil: xml_grep, où vous écririez probablement ce que vous voulez comme xml_grep -t '/html/head/title' xhtmlfile.xhtml > titleOfXHTMLPage.txt (l'option -t vous donne le résultat sous forme de texte au lieu de xml )

4
mirod

Bien que de nombreux utilitaires de console prêts à l’emploi puissent faire ce que vous voulez, il vous faudra probablement moins de temps pour écrire quelques lignes de code dans un langage de programmation général tel que Python. peut facilement s'étendre et s'adapter à vos besoins.

Voici un script python qui utilise lxml pour l'analyse - il prend le nom d'un fichier ou une URL en tant que premier paramètre, une expression XPath en tant que second paramètre et imprime le chaînes/nœuds correspondant à l'expression donnée.

Exemple 1

#!/usr/bin/env python
import sys
from lxml import etree

tree = etree.parse(sys.argv[1])
xpath_expression = sys.argv[2]

#  a hack allowing to access the
#  default namespace (if defined) via the 'p:' prefix    
#  E.g. given a default namespaces such as 'xmlns="http://maven.Apache.org/POM/4.0.0"'
#  an XPath of '//p:module' will return all the 'module' nodes
ns = tree.getroot().nsmap
if ns.keys() and None in ns:
    ns['p'] = ns.pop(None)
#   end of hack    

for e in tree.xpath(xpath_expression, namespaces=ns):
    if isinstance(e, str):
        print(e)
    else:
        print(e.text and e.text.strip() or etree.tostring(e, pretty_print=True))

lxml peut être installé avec pip install lxml. Sur Ubuntu, vous pouvez utiliser Sudo apt install python-lxml.

Usage

python xpath.py myfile.xml "//mynode"

lxml accepte également une URL en entrée:

python xpath.py http://www.feedforall.com/sample.xml "//link"

Remarque : Si votre code XML a un espace de nom par défaut sans préfixe (par exemple, xmlns=http://abc...), vous devez utiliser le préfixe p (fourni par le 'hack') dans vos expressions, par exemple //p:module pour obtenir les modules d'un fichier pom.xml. Si le préfixe p est déjà mappé dans votre XML, vous devrez modifier le script pour utiliser un autre préfixe.


Exemple 2

Un script unique qui sert uniquement à extraire les noms de modules d'un fichier maven Apache. Notez que le nom de noeud (module) est préfixé avec l'espace de nom par défaut {http://maven.Apache.org/POM/4.0.0}:

pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
    <modules>
        <module>cherries</module>
        <module>bananas</module>
        <module>pears</module>
    </modules>
</project>

module_extractor.py :

from lxml import etree
for _, e in etree.iterparse(open("pom.xml"), tag="{http://maven.Apache.org/POM/4.0.0}module"):
    print(e.text)
2
ccpizza

Après quelques recherches sur la traduction entre les formats Linux et Windows des chemins de fichiers dans des fichiers XML, j'ai trouvé des tutoriels et des solutions intéressantes sur:

2
user485380

Eh bien, vous pouvez utiliser l'utilitaire xpath. Je suppose que XML :: Xpath de Perl le contient.

2
alamar

La méthode de Yuzem peut être améliorée en inversant l'ordre des signes < et > dans la fonction rdom et les affectations de variables, de sorte que:

rdom () { local IFS=\> ; read -d \< E C ;}

devient:

rdom () { local IFS=\< ; read -d \> C E ;}

Si l'analyse ne se fait pas comme cela, la dernière balise du fichier XML n'est jamais atteinte. Cela peut être problématique si vous souhaitez générer un autre fichier XML à la fin de la boucle while.

0
michaelmeyer

Cela fonctionne si vous voulez des attributs XML:

$ cat alfa.xml
<video server="asdf.com" stream="H264_400.mp4" cdn="limelight"/>

$ sed 's.[^ ]*..;s./>..' alfa.xml > alfa.sh

$ . ./alfa.sh

$ echo "$stream"
H264_400.mp4
0
Steven Penny