web-dev-qa-db-de.com

Wie kann man XML in Bash analysieren?

Im Idealfall möchte ich Folgendes tun können:

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

Dies ist eigentlich nur eine Erklärung von Yuzems Antwort, aber ich hatte nicht das Gefühl, dass jemand anders so viel bearbeiten sollte, und Kommentare erlauben keine Formatierung, also ...

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

Nennen wir das "read_dom" anstelle von "rdom", platzieren Sie es ein wenig und verwenden Sie längere Variablen:

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

Okay, es definiert eine Funktion namens read_dom. In der ersten Zeile wird IFS (das Eingabefeldtrennzeichen) für diese Funktion als lokal festgelegt und in> geändert. Das heißt, wenn Sie Daten lesen, anstatt sie automatisch nach Leerzeichen, Tabulatoren oder Zeilenumbrüchen aufzuteilen, werden sie nach ">" aufgeteilt. In der nächsten Zeile wird angegeben, dass die Eingabe von stdin gelesen werden soll. Anstatt an einer neuen Zeile anzuhalten, halten Sie an, wenn Sie ein <-Zeichen sehen (das -d für das Trennzeichen). Was gelesen wird, wird dann über das IFS aufgeteilt und der Variablen ENTITY und CONTENT zugeordnet. Also nimm folgendes:

<tag>value</tag>

Beim ersten Aufruf von read_dom Wird eine leere Zeichenfolge abgerufen (da das '<' das erste Zeichen ist). Das wird von IFS in nur '' aufgeteilt, da es kein '>' Zeichen gibt. Read weist dann beiden Variablen eine leere Zeichenfolge zu. Der zweite Aufruf erhält den String 'tag> value'. Das wird dann vom IFS in die beiden Felder 'Tag' und 'Wert' aufgeteilt. Lesen Sie dann ordnet die Variablen wie: ENTITY=tag Und CONTENT=value. Der dritte Aufruf erhält den String '/ tag>'. Das wird vom IFS in die beiden Felder '/ tag' und '' aufgeteilt. Lesen Sie dann ordnet die Variablen wie: ENTITY=/tag Und CONTENT=. Der vierte Aufruf gibt einen Status ungleich Null zurück, da das Dateiende erreicht ist.

Jetzt hat seine while-Schleife ein bisschen aufgeräumt, um den obigen Werten zu entsprechen:

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

In der ersten Zeile steht nur: "Während die Funktion read_dom den Status Null zurückgibt, gehen Sie wie folgt vor." In der zweiten Zeile wird überprüft, ob das Objekt, das wir gerade gesehen haben, "title" ist. Die nächste Zeile gibt den Inhalt des Tags wieder. Die vier Zeilen enden. Wenn es nicht das Titelelement war, wird die Schleife in der sechsten Zeile wiederholt. Wir leiten "xhtmlfile.xhtml" in die Standardeingabe um (für die Funktion read_dom) Und leiten die Standardausgabe in "titleOfXHTMLPage.txt" um (das Echo von früher in der Schleife).

Geben Sie nun Folgendes an (ähnlich wie beim Auflisten eines Buckets in S3) für 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>

und die folgende Schleife:

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

Du solltest bekommen:

 => 
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 => 

Wenn wir also eine while -Schleife wie die von Yuzem schreiben würden:

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

Wir würden eine Liste aller Dateien im S3-Bucket erhalten.

[~ # ~] edit [~ # ~] Wenn aus irgendeinem Grund local IFS=\> nicht funktioniert und Sie es global einstellen , sollten Sie es am Ende der Funktion zurücksetzen wie:

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

Andernfalls werden alle Zeilen, die Sie später im Skript aufteilen, durcheinander gebracht.

EDIT 2 Zum Aufteilen von Attributnamen/Wert-Paaren können Sie die Funktion read_dom() folgendermaßen erweitern:

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

Dann schreiben Sie Ihre Funktion, um die gewünschten Daten zu analysieren:

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
}

Dann, während Sie read_dom Aufrufen parse_dom:

while read_dom; do
    parse_dom
done

Geben Sie dann das folgende Beispiel-Markup an:

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

Sie sollten diese Ausgabe erhalten:

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

EDIT 3 Ein anderer Benutzer gab an, Probleme mit FreeBSD zu haben, und schlug vor, den Exit-Status vor dem Lesen zu speichern und ihn an zurückzugeben das Ende von read_dom wie:

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

Ich sehe keinen Grund, warum das nicht funktionieren sollte

142
chad

Das geht ganz einfach mit bash. Sie müssen nur diese Funktion hinzufügen:

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

Jetzt können Sie rdom wie read verwenden, aber für HTML-Dokumente. Beim Aufruf von rdom wird das Element der Variablen E und der Inhalt der Variable C zugewiesen.

Zum Beispiel, um das zu tun, was Sie tun wollten:

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

Befehlszeilentools, die über Shell-Skripte aufgerufen werden können, umfassen:

  • 4xpath - Befehlszeilen-Wrapper um das 4Suite -Paket von Python
  • XMLStarlet
  • xpath - Befehlszeilen-Wrapper für die XPath-Bibliothek von Perl
  • Xidel - Funktioniert sowohl mit URLs als auch mit Dateien. Funktioniert auch mit JSON

Ich verwende auch xmllint und xsltproc mit kleinen XSL-Transformationsskripten, um die XML-Verarbeitung über die Befehlszeile oder in Shell-Skripten durchzuführen.

54
Nat

Sie können das Dienstprogramm xpath verwenden. Es wird mit dem Perl XML-XPath-Paket installiert.

Verwendung:

/usr/bin/xpath [filename] query

oder XMLStarlet . Um es auf opensuse zu installieren, benutze:

Sudo zypper install xmlstarlet

oder Versuche cnf xml auf anderen Plattformen.

22
Grisha

Das ist ausreichend ...

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

Check out XML2 from http://www.ofb.net/~egnor/xml2/ das XML in eine Zeile konvertiert -orientiertes Format.

5
simon04

ausgehend von der Antwort des Chads ist hier die KOMPLETTE Arbeitslösung zum Parsen von UML mit korrekter Behandlung von Kommentaren mit nur 2 kleinen Funktionen (mehr als 2 bu können Sie sie alle mischen). Ich sage nicht, dass Chads eine überhaupt nicht funktioniert hat, aber es gab zu viele Probleme mit schlecht formatierten XML-Dateien: Man muss also etwas schwieriger sein, mit Kommentaren und fehlplatzierten Leerzeichen/CR/TAB/etc umzugehen.

Der Zweck dieser Antwort ist es, jedem, der UML ohne komplexe Werkzeuge mit Perl analysieren möchte, sofort einsatzbereite Bash-Funktionen zu bieten python oder irgendetwas anderes. Was mich betrifft, ich Ich kann weder cpan noch Perl-Module für das alte Betriebssystem installieren, an dem ich arbeite, und python ist nicht verfügbar.

Zunächst eine Definition der in diesem Beitrag verwendeten UML-Wörter:

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

EDIT: aktualisierte Funktionen, mit Handle von:

  • Websphere-XML (XML- und XMLNS-Attribute)
  • muss ein kompatibles Terminal mit 256 Farben haben
  • 24 Graustufen
  • kompatibilität hinzugefügt für IBM AIX bash 3.2.16 (1)

Die erste Funktion ist die xml_read_dom, die von xml_read rekursiv aufgerufen wird:

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
}

und der zweite:

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
}

und zuletzt die Funktionen rtrim, trim und echo2 (to stderr):

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

Einfärbung:

oh und du brauchst ein paar nette dynamische Variablen zum Kolorieren, die zuerst definiert und auch exportiert werden:

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"'

So laden Sie all das Zeug:

Entweder Sie wissen, wie Sie Funktionen erstellen und über FPATH (ksh) oder eine Emulation von FPATH (bash) laden.

Wenn nicht, kopieren Sie einfach alles in die Befehlszeile.

Wie funktioniert es:

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

Im Debug-Modus (-d) werden Kommentare und analysierte Attribute nach stderr gedruckt

5
scavenger

Ein anderes Kommandozeilenwerkzeug ist mein neues Xidel . Es unterstützt auch XPath 2 und XQuery, im Gegensatz zu dem bereits erwähnten xpath/xmlstarlet.

Der Titel kann wie folgt gelesen werden:

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

Und es hat auch eine coole Funktion, um mehrere Variablen nach Bash zu exportieren. Beispielsweise

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

setzt $title zum Titel und $imgcount auf die Anzahl der Bilder in der Datei, die so flexibel sein sollte, wie sie direkt in bash zu analysieren.

4
BeniBela

Mir ist kein reines Shell-XML-Parsing-Tool bekannt. Sie benötigen also höchstwahrscheinlich ein Tool, das in einer anderen Sprache geschrieben ist.

Mein XML :: Twig Perl-Modul enthält ein solches Tool: xml_grep, wo würdest du wahrscheinlich schreiben was du willst als xml_grep -t '/html/head/title' xhtmlfile.xhtml > titleOfXHTMLPage.txt (das -t Option gibt Ihnen das Ergebnis als Text anstelle von xml)

4
mirod

Es gibt zwar einige vorgefertigte Konsolendienstprogramme, die möglicherweise das tun, was Sie wollen, aber in einer universellen Programmiersprache wie Python = die Sie einfach erweitern und an Ihre Bedürfnisse anpassen können.

Hier ist ein python Skript, das lxml zum Parsen verwendet - es verwendet den Namen einer Datei oder einer URL als ersten Parameter, einen XPath-Ausdruck als zweiten Parameter und gibt die Zeichenfolgen/Knoten aus, die dem angegebenen Ausdruck entsprechen.

Beispiel 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 kann mit pip install lxml installiert werden. Auf Ubuntu können Sie Sudo apt install python-lxml verwenden.

Verwendung

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

lxml akzeptiert auch eine URL als Eingabe:

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

Hinweis : Wenn Ihre XML einen Standardnamensraum ohne Präfix hat (z. B. xmlns=http://abc...), müssen Sie die p verwenden. Präfix (bereitgestellt durch den 'Hack') in Ihren Ausdrücken, z //p:module, um die Module aus einer pom.xml-Datei abzurufen. Falls das Präfix p bereits in Ihrer XML-Datei zugeordnet ist, müssen Sie das Skript ändern, um ein anderes Präfix zu verwenden.


Beispiel 2

Ein einmaliges Skript, das dem engen Zweck dient, Modulnamen aus einer Apache-Maven-Datei zu extrahieren. Beachten Sie, wie dem Knotennamen (module) der Standardnamespace {http://maven.Apache.org/POM/4.0.0} vorangestellt wird:

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

Nach einigen Recherchen zur Übersetzung der Dateipfade in XML-Dateien zwischen Linux- und Windows-Formaten fand ich interessante Tutorials und Lösungen zu folgenden Themen:

2
user485380

Nun, Sie können das Dienstprogramm xpath verwenden. Ich denke, Perls XML :: Xpath enthält es.

2
alamar

Die Methode von Yuzem kann verbessert werden, indem die Reihenfolge der Zeichen < Und > In der Funktion rdom und den Variablenzuweisungen umgekehrt wird.

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

wird:

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

Wenn das Parsen nicht so durchgeführt wird, wird das letzte Tag in der XML-Datei nie erreicht. Dies kann problematisch sein, wenn Sie beabsichtigen, eine andere XML-Datei am Ende der while -Schleife auszugeben.

0
michaelmeyer

Dies funktioniert, wenn Sie XML-Attribute wünschen:

$ 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