Az XMLStarlet programmal nagyon sok XML-lel kapcsolatos feladatot hajthatunk végre kényelmes, parancssorról vezérelhető felületen.Nagyszerűen használható a példák minél egyszerűbb környezetben való kipróbálására, hiszen sokszor a befoglaló program (praktikusan Java program) megírása bonyolult lenne. A program írója, Mikhail Grushinskiy a programot a szabad szoftverek esetében megszokott MIT licensz alatt tette elérhetővé.Ez azt jelenti, hogy saját termékeinkbe is beépíthetjük.
A program rendelkezik a szokásos információs opciókkal:
xmlstarlet --version -- verzió információ megjelenítése
xmlstarlet –-help -- segítő képernyő megmutatása
A lényegi funkcionalitást különböző alparancsok alatt valósították meg:
xmlstarlet ed -- XML fájlok módosítása
xmlstarlet sel -- XPath kifejezések értelmezése XML dokumentumon
xmlstarlet tr -- XSLT traanszformáció végrehajtása XML dokumentumon
xmlstarlet val -- XML dokumentum validálása, esetleg DTD, XSD vagy RelaxNG segítségével
xmlstarlet fo -- XML dokumentumok formázása
xmlstarlet el -- XML dokumentum struktúrájának megmutatása, mintha könyvtárstruktúra lenne
xmlstarlet c14n -- XML kanonizálás
xmlstarlet ls -- a UNIX ls parancsának XML kimenettel rendelkező verziója
xmlstarlet esc -- XML-ben kivételesen kezelt karakterek stringbeli eszképelése
xmlstarlet unesc -- az esc inverze
Mindegyik parancsról lekérdezhető az aktuális dokumentációja az xmlstarlet <parancs> --help kiadásával.
Erre a feladatra a select parancs való, ami sel-ként is rövidíthető, lényegében egy XSLT-t állítunk össze parancssori kapcsolókkal, amit aztán le is futtatunk XML fileokra.
Forma:
xmlstarlet select <globális kapcsolók> {<template>} [ <xml-file> … ]
A globális opciók közül a fontosabbak:
-C -- a generált XSLT kiírása
-T -- a kimenet szöveg (xml helyett)
-I -- a kimenet legyen indentált
-D -- ne hagyjuk el az XML deklarációt
-B -- nem szignifikáns szóközök elhagyása a kimenetből
--net -- DTD-k és entitások letöltése szükség esetén az internetről
Template definiálása: -t <opciók>, ahol a lehetséges opciók a template leírásához:
-c <xpath> -- XPath kifejezés által meghatározott rész másolása
-v <xpath> -- XPath kifejezés kiértékelése
-o <string> -- string kiírása a kimenetben
-n -- egy újsor kiírása a kimenetben
-m <xpath> -- XPath kifejezés illesztése (for-each)
-i <t-xpath> -- tesztelő XPath kifejezéssel if generálása (<xsl:if test=”t-xpath”>)
-e <name> -- adott nevű elem létrehozása (<xsl:element name=”name”>)
-a <name> -- attribútum létrehozása (<xs:attribute name=”name”>)
-b -- előző szint lezárása (pl. elem, attribútum)
-s X:Y:Z xp -- csak –m után használva xp kifejezés szerinti X:Y:Z módú rendezés:
ha X az az A – növekvő sorrend
ha X az a D – csökkenő sorrend
ha Y az az N – szám szerinti rendezés
ha Y az a T – szöveg szerinti rendezés
ha Z az az U – nagybetűsek előre
ha Z az az L – kisbetűsek előre
Nézzünk egy példát!
Tegyük fel, hogy az alábbi parancssort futtatjuk le:
xml sel -t -c "xpath0" -m "xpath1" -m "xpath2" -v "xpath3" \
-t -m "xpath4" -c
"xpath5"
Ez pontosan ekvivalens azzal, mintha az alábbi módon megírt XSLT-t alkalmaznánk:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:call-template name="t1"/>
<xsl:call-template name="t2"/>
</xsl:template>
<xsl:template name="t1">
<xsl:copy-of select="xpath0"/>
<xsl:for-each select="xpath1">
<xsl:for-each select="xpath2">
<xsl:value-of select="xpath3"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="t2">
<xsl:for-each select="xpath4">
<xsl:copy-of select="xpath5"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Érdemes megjegyezni, hogy a XMLStarlet a libxslt nevű programfüggvény-gyűjteményt használja, így annak dokumentációja pár specialitást illetően szintén irányadó lehet.
Erre a feladatra az edit parancs való, ami ed-ként is rövidíthető.
Forma: xmlstarlet edit <globális kapcsolók> {<akció>} [ <xml-file> … ]
A globális opciók közül a fontosabbak:
-P -- eredeti formázás megtartása
-S -- nem szignifikáns szóközök elhelyezkedésének megtartása
-I -- XML deklaráció elhagyása
-O -- ne hagyjuk el az XML deklarációt
Akció definiálása:
-d <xpath> -- XPath kifejezés által meghatározott rész törlése
-i <xpath> -t elem|text|attr –n <név> -v <érték>
-- XPath kifejezés elé a megfelelő típussal, névvel és értékkel rendelkező csúcs beszúrása
-a <xpath> -t elem|text|attr –n <név> -v <érték>
-- XPath kifejezés után a megfelelő típussal, névvel és értékkel rendelkező csúcs beszúrása
-s <xpath> -t elem|text|attr –n <név> -v <érték>
-- XPath kifejezés által meghatározott csúcs belsejébe beszúrás a megfelelő típussal, névvel és értékkel az eddigi gyerekek után
-m <x1> <x2> -- a UNIX mv parancsa XML-re, x1 XPath által meghatározott rész x2-be mozgatása
-r <x1> -v n -- x1 által meghatározott XPath kifejezés csúcsának új neve n lesz
-u <x1> -v n -- x1 által meghatározott XPath kifejezés csúcsának új értéke n lesz
Tekintsük az alábbi nagyon egyszerű XML dokumentumot, amit
aztán a most bemutatott parancsokkal fogunk bővíteni/szűkíteni/átalakítani.
<?xml version=”
<test>
<first/>
<second/>
</test>
Csúcs törlése:
% xmlstarlet ed –d //test/first test.xml
<?xml version=”
<test>
<second/>
</test>
Csúcs beszúrása meglévő csúcs elé:
% xmlstarlet ed –i //test/second –t elem –n insert –v now test.xml
<?xml version=”
<test>
<first/>
<insert>now</insert>
<second/>
</test>
Csúcs beszúrása meglévő csúcs mögé:
% xmlstarlet ed –a //test/second –t elem –n insert –v now test.xml
<?xml version=”
<test>
<first/>
<second/>
<insert>now</insert>
</test>
Csúcs létrehozása meglévő csúcs új leszármazottjaként:
% xmlstarlet ed –s //test/second –t elem –n insert –v now test.xml
<?xml version=”
<test>
<first/>
<second>
<subnode>now</subnode>
</second>
</test>
Részfa mozgatása/áthelyezése:
% xmlstarlet ed –m //test/first //test/second test.xml
<?xml version=”
<test>
<second>
<first/>
</second>
</test>
Csúcs átnevezése:
% xmlstarlet ed –r //test/first –v new-name test.xml
<?xml version=”
<test>
<new-name/>
<second/>
</test>
Csúcs értékének módosítása:
% xmlstarlet ed –u //test/first –v new-value test.xml
<?xml version=”
<test>
<first>new-value</first>
<second/>
</test>
Egyszerre több akciót is véghezvihetünk, pl.:
% xmlstarlet ed –s //test/second –t elem –n subnode –v now –m //test/second/subnode //test –r //test/subnode –v insert test.xml
<?xml version=”
<test>
<first/>
<second/>
<insert>now</insert>
</test>
Lehetőség van az aktuális könyvtár XML-ként való listázására az xmlstarlet ls paranccsal. Ez többek közt kitűnő tesztadatok biztosításához, mikor az XML-ről tanulunk. Lássunk egy példakimenetet az otthoni számítógépünk /tmp alkönyvtárán:
<dir>
<d p="rwxrwxrwt" a="20060112T170548Z" m="20060112T170336Z" s="4096" n=".X11-unix"/>
<d p="rwxrwxrwt" a="20060112T170548Z" m="20060112T170405Z" s="4096" n=".ICE-unix"/>
<d p="rwx------" a="20060112T170353Z" m="20060112T214414Z" s="4096" n="kde-risko"/>
<f p="r--r--r--" a="20060112T170553Z" m="20060112T170553Z" s="11" n=".X0-lock"/>
<d p="rwx------" a="20060112T170350Z" m="20060112T170350Z" s="4096" n="ssh-EZsmXc1230"/>
<d p="rwx------" a="20060112T170350Z" m="20060112T170350Z" s="4096" n="ssh-szQdIQ1230"/>
<d p="rwx------" a="20060112T170353Z" m="20060112T214414Z" s="4096" n="ksocket-risko"/>
<d p="rwx------" a="20060112T170406Z" m="20060112T170407Z" s="4096" n="mcop-risko"/>
<d p="rwx------" a="19700101T000000Z" m="20060112T190225Z" s="4096" n="orbit-risko"/>
<d p="rwx------" a="20060112T170445Z" m="20060112T190225Z" s="4096" n="gconfd-risko"/>
<f p="rw-r--r--" a="20060112T190330Z" m="20050131T053735Z" s="1184" n="ziyi_key_2005.asc"/>
<d p="rwxr-xr-x" a="20060112T195041Z" m="20060112T195200Z" s="4096" n="timicd"/>
<s p="rwxr-xr-x" a="20060112T221912Z" m="20060112T194836Z" s="0" n="xmms_risko.0"/>
<f p="rw-------" a="20060112T202405Z" m="20060112T202409Z" s="50814" n="tetex.postinst.XXQlIOuk"/>
<f p="rw-r--r--" a="20060112T220343Z" m="20060112T215243Z" s="58" n="test.xml"/>
</dir>
Természetesen egy ilyen kimenet az ember számára nehezen
olvasható, azonban nagyon könnyen átalakíthatjuk XSLT-vel valami olvasható
formátumra. Gondoljuk meg, hogy egyszerű
UNIX pipe-okkal beadhatjuk ezt a kimentet egy következő, xmlstarlet sel parancsnak.
Legyen a feladat az, hogy emuláljuk a UNIX ls -1 kimenetét, de azzal a módosítással, hogy a könyvtárnevek végére egy ’/’ jelet teszünk, így a tömör kimenetben is könnyedén látszik, ha valami könyvtár. A megoldó parancs:
xmlstarlet ls | xmlstarlet sel –T –t –m ‘//dir/*[not(self::d)]’ –v ‘@n’ –n –t –m ‘//dir/d’ –v ‘@n’ –o ‘/’ –n
Az első templateben kizártuk az XPath kifejezéssel a
könyvtárakat és ezért csak a név attribútumot, majd egy új sort írattunk
ki. A második template-ben azonban csak
a könyvtárakat járjuk be és mindegyik könyvtárnév után, de még az új sor előtt
egy / jelet is kiírunk a kimenetben. A
–T opcióval jeleztük, hogy szöveges kimenetet kérünk, nem XML-t.
XML dokumentumokban a <, >, & karakterek a jelölésrendszer részét képezik, így nem tudjuk például azt az egyenlőtlenséget leírni, hogy 2<3.
Ehelyett már a HTML-ből megszokott módon a következőt kell
írnunk: 2<
Az XMLStarlet programcsomag tartalmaz egy parancsot ezen konverzió és az inverzének elvégzésére is, lássuk:
risko@bubble:/tmp$ xmlstarlet esc '2<3 && 5>6'
2<3 && 5>6
risko@bubble:/tmp$ xmlstarlet esc '2<3 && 5>6' | xmlstarlet unesc
2<3 && 5>6