views:

694

answers:

4

I'm trying to parse out values from a Widget config.xml using shell. I do want to use sed for this task. If there is something that sucks less than xsltproc, I'd love to know.

In this example I am after the id attribute value from the config.xml below:

<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="http://example.org/exampleWidget" version="2.0 Beta" height="200" width="200">
<name short="123">Foo Widget</name>
</widget>

I wish it was as simple as Jquery's attr: var id = $("widget").attr("id");

Currently this shell code utilising xsltproc fails:

snag () {
TMP=$(tempfile)
cat << EOF > $TMP
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="utf-8" indent="no"/>
<xsl:template>
<xsl:value-of select="$1"/>
</xsl:template>
</xsl:stylesheet>
EOF

echo $(xsltproc $TMP config.xml)
rm -f $TMP
}

ID=$(snag "widget/@id")

if test "$ID" = "http://example.org/exampleWidget"
then
 echo Mission accomplished.
else
 echo "<$ID> is wrong."
fi
A: 

template match="widget"

select value-of="@id"

Jamie Kitson
A: 

<xsl:template xmlns:wgt="http://www.w3.org/ns/widgets" match="/wgt:widget"> <xsl:select value-of="@id" /> </xsl:template>

dontcallmedom
hendry@x61 shell$ sh foo.sh /tmp/file3jey7M:3: parser error : Specification mandate value for attribute value-of <xsl:select value-of select="@id" /> ^ /tmp/file3jey7M:3: parser error : attributes construct error <xsl:select value-of select="@id" /> ^ /tmp/file3jey7M:3: parser error : Couldn't find end of Start Tag select line 3 <xsl:select value-of select="@id" /> ^ cannot parse /tmp/file3jey7M
hendry
+1  A: 

XMLStarlet (http://xmlstar.sourceforge.net/) is a nice command line tools that supports such queries:

xmlstarlet sel -N w=namespace -T -t -m "/w:widget/@id" -v . -n config.xml

Jörn Horstmann
Have you tried this command? It doesn't work for me on 1.0.1.
hendry
I forgot the widget namespace in the first try. You have to replace 'namespace' with the value from your xml, Stackoverflow won't let new users paste more than one url.
Jörn Horstmann
How extraordinary, it works. `hendry@x61 shell$ xmlstarlet sel -N w="http://www.w3.org/ns/widgets" -T -t -m "/w:widget/@id" -v . -n config.xmlhttp://webvm.net/widgets/123`However there is an aboniation of switches there. Insane!!
hendry
A: 

You don't need XSLT if you're not doing a transform. If you only need to grab a value use XPath.

There's an xpath program that comes with Perl's XML::XPath module.

From the shell: ID=$(xpath config.xml 'string(/widget/@id)' )

( The string() function is to get only the value of the id.

/widget/@id by itself returns "id=value" )

If you only need to produce some other output depending on the value, you could do it all in xslt. There are also other XPath implementations available from other scripting languages: I've used Java's XPath from both rhino and Jython. There's also XQuery from the command line with Saxon.

Steven D. Majewski
Xpath looks really heavy compared to `xmlstarlet`.
hendry