This post discusses namespaces in XML documents and XSLT 1.0 stylesheets. In particular, it demonstrates a number of techniques to control namespace prefixes and declarations in outputted documents.
|
|
||
|
This post discusses namespaces in XML documents and XSLT 1.0 stylesheets. In particular, it demonstrates a number of techniques to control namespace prefixes and declarations in outputted documents. Earlier this year I wrote a number of posts about monitoring and interacting with D-Bus using shell scripts. In this post I look at using Ruby to monitor and interact with D-Bus enabled applications. In previous posts, I discussed the SpiderMonkey command line shell js and how to add support to it to enable full access (read, write, create, copy, delete, etc.) to the local filesystem via the File object and the NSPR library. While rumaging around in the source code and documentation for js, I found that js partially supported the EX4 XML extension via a user configurable option. This post looks at what it takes to load an XML document into js from your local filesystem, process it and write out the resulting document to your local filesystem using File objects and the E4X extension. The ECMAScript for XML (E4X) (ECMA-357) specification adds native support for XML objects and XMLList objects to the JavaScript programming language. This standard was first published in 2004 and was based on XML extensions provided in the BEA (now Oracle) Weblogic Workshop product. These extensions were designed by Terry Lucas and John Schneider who led the ECMAScript for XML (E4X) initiative. The basis idea behind E4X was that declarative languages such as XSL and XPATH are too complex for the average programmer to quickly learn and therefore a simpler way of accessing and manipulating XML documents was needed. Personally I do not agree with that assertion. As an aside, currently Schneider is founder and CEO at AgileDelta which developed the Efficient XML binary format specification which I plan to write about in a future post. A W3C working group is currently developing the EXI specification which is based on the AgileDelta specification. A recent problem that was posed to me concerned how to copy the entire contents of an XML document with certain exceptions. Turns out that the simplest way to handle this requirement in XSLT1.0 was to include the standard XSL identity template in my stylesheet and add another template to handle the exception. A simple example will make things clearer. Suppose we have the following XML document (which I shamelessly copied from W3Schools.com and modified to simplify) and we want to copy this document in its entirety except for details of CDs by a specific artist. <?xml version="1.0"?> <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Columbia</COMPANY> <YEAR>1985</YEAR> </CD> <CD> <TITLE>Hide your heart</TITLE> <ARTIST>Bonnie Tyler</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS Records</COMPANY> <YEAR>1988</YEAR> </CD> <CD> <TITLE>Greatest Hits</TITLE> <ARTIST>Dolly Parton</ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>RCA</COMPANY> <YEAR>1982</YEAR> </CD> <CD> <TITLE>One night only</TITLE> <ARTIST>Bee Gees</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Polydor</COMPANY> <YEAR>1998</YEAR> </CD> <CD> <TITLE>Sylvias Mother</TITLE> <ARTIST>Dr.Hook</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS</COMPANY> <YEAR>1973</YEAR> </CD> <CD> <TITLE>Maggie May</TITLE> <ARTIST>Rod Stewart</ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>Pickwick</COMPANY> <YEAR>1990</YEAR> </CD> </CATALOG> Below is the stylesheet. It accepts one parameter, i.e. the name, or part of the name, of an artist. It copies all nodes and attributes to the output document except those nodes and attributes related to the artist whose name matches or is is a superset of the inputted string. <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="artist"></xsl:param> <xsl:output method="xml"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="/CATALOG/CD"> <xsl:if test="not(contains(./ARTIST,$artist))"> <xsl:copy-of select="." /> </xsl:if> </xsl:template> </xsl:stylesheet> The first template is the standard identity template from the XSL 1.0 Transformations Recommendation. It matches all attributes and all nodes being children of other nodes, and copies them to the output document. The second template cancels the automatic copying of the <CD> nodes and children, checks to see that the name, or part of the name, of the artist does not match the search string, and only does a deep copy of the nodes and attributes to the output document if there is no match. Assuming you are on a Linux system, you can use the command line utility xsltproc (which is part of the XSLT C library for GNOME) to transform the input document into the following output document when "Stewart" is passed as a parameter to the stylesheet. BTW, note the use of Java style string quotes for the parameter string. $ xsltproc -param artist "’Stewart’" file.xsl file.xml Here is the output document. It is a copy of the input document except the "record" for the Rod I tripped over the issue of using a variable as a predicate in an attribute match again today. This has happened to me before and I should know better but it have been a while since I had to do any serious XSLT1 coding. I now mostly work with XSLT2. Since there is not much easily found information out there on the Internet about this issue, I decided to write this post to explain the problem. |
||
|
Copyright © 2005-2012 Finnbarr P. Murphy. All Rights Reserved. |
||