Once upon a time, I wondered whether there was a natural law dictating three choices. Now, I understand that three is the minimum number to graphically demonstrate the need for compromise. Two makes it look like you’re pitting one against the other and four makes the choices too complex.
The bottom line is that any commercially desirable goal requires compromise. The sooner you accept the need for compromise, the sooner you can make some decisions and get on with it.
Note to self: reserve time at Dig This next time you’re in Las Vegas.
The 10-employee park has five pieces of machinery, including a pair of Caterpillar D5 track-type bulldozers and three Caterpillar 315CL hydraulic excavators. Dig This sells three-hour packages that consist of a 30-minute safety and operation orientation followed by two hours of maneuvering either a bulldozer or excavator.
There are numerous deserving charities that need our support. Especially now. But make a donation and you can expect an unending stream of solicitations for more donations as your reward.
So wouldn’t it be nice if we could make anonymous donations via the IRS. That way we could get a tax receipt without revealing our identity.
After 16 years of service, it is time to say good bye to my 1995 Infiniti G20.
I had been debating between the Mazda 626, Acura Integra, and Infiniti G20 for a while. And I made my move when when the Hendrick Auto Group ran an ad for a white 5-speed G20 in the Sunday Chronicle.
My G20 carried me on a painful commute from the San Ramon Valley to Silicon Valley for several years until I couldn’t endure it any more. It waited patiently in my CA garage for the year or two that I spent in Manhattan. And it rejoined me in Connecticut when I shifted stakes from CA to CT for good.
Sixteen years is a good run for a car. And it still runs great. But my wife upgraded her car and I’m upgrading to her 2005 Subaru. At least I’ll still get to see the G20 when the new owner (a colleague at work) brings it to the office.
XSL is not just a transformational process, you can also add information content during the transformation. The following transform tweaks the identity transform to add a date element as the first child of the root.
Here are our changes:
Access the EXSLT extensions for dates and times in Xalan-J by adding the date: namespace.
Exclude the date: namespace from the results by adding it to the exclude-result-prefixes attribute.
Define an XSL date param and initialize it to the current date. Note that the param value specified in the transform may be externally overridden.
Explicitly match on the root element: match=”/*”
Use the name() function to create an element with the same name as the root
Apply the identity template to any attributes of the root element
Add a new date element that contains the value of the date param
Apply the identity template to any children of the root element
Producing our new echoWithDate.xsl transform file:
Now, let’s update the XSL Servlet to add support for parameter values. Previously, we used the path information to specify the transform to run. Here, we extend that to include slash delimited, comma separated parameter name/value pairs:
/transform-name/param1-name,param1-value/param2-name,param2-value
Here is the updated code from XSL servlet doPost method:
Here’s the updated XSL Servlet packaged as a war file. Once again, you’ll need to add serializer.jar, xalan.jar and xml-apis.jar from Xalan-J to the web-application WEB-INF/lib directory.
My Connecticut dead-tree edition of the New York Times has no mention of yesterday’s Stanford - Notre Dame football game. Not even a line listing the score in the Scoreboard.
I knew Notre Dame football was slipping off the radar, but I didn’t realize how far the process had progressed.
So far, we haven’t done anything with soapUI that couldn’t be done with curl and a shell script. One of the advantages of soapUI over curl is the built-in support for groovy scripting .
The following example shows the use of a groovy load script to insure that properties are properly initialized. A project load script is specified in the lower load pane of the of the project panel.
Our example simply looks at the project id property and then sets the firstName and lastName properties appropriately. The load script is automatically executed when the project is loaded and can be manually executed by clicking on the green triangle in the upper left corner above the load script pane.
After executing the load script, the properties pane displays the corresponding values. It is also possible to add, define, organize, save [to file] and load [from file] properties directly from this pane.
Once the property is defined, then it is easily added to our post data in the form ${#scope#property-name}. There are 3 scopes: Project, TestSuite and TestCase; only Project scope is available at this point. And we can see the property values in the response xml.
soapUI is a “open source functional testing tool for Web Services”. In this post, we’ll add the XSL Servlet as a soapUI project.
To help you get started, here is the XSL servlet as a java war file. This war requires the addition of serializer.jar, xalan.jar and xml-apis.jar from Xalan-J to the web-application WEB-INF/lib directory to run.
First, create a new project in soapUI. That bring up the dialog shown below. For this example, I’ve named the new service Ideoplex, specified the base url for the service as http://localhost:8080/xsl/transform and requested that we proceed to add a REST resource as our next step.
Name the resource “Get environment” and specify an endpoint of environment (this will be appended to the service endpoint defined for our project.
Name the method “Get Environment” and verify that the HTTP Method is “GET”.
And execute this request by clicking on the green triangle in the upper left. soapUI will display the response (the environment.xsl transform configured in the java web application) in the right window pane with a response time in the window footer.
Repeat the preceding 3 steps to add the corresponding POST request. Be sure to specify POST as the HTTP Method when defining the Method and to add a valid xml file as input to the Request.
Continue and add GET and POST methods for the echo and remove transforms. That should result in a the soapUI project file linked here.
Before we deploy our XSL servlet, let’s look at some simple transforms from the command line.
First, a simple transform that detects the root node and then outputs the xalan environment. Naturally, this will only work when you’re using xalan .
Next, let’s look at the “identity” transform. There is a single template directive that matches on attributes or elements (@* and node() respectively). For each attribute or element entity, we copy the current attribute or element and then we recursively apply the template to any children of the current element.
Note that this simple transform only copies attributes and elements. Other entities, such as comments, will be ignored.
And finally, a transform that removes any element named “remove” along with its children. We start with the identity transform, adding a priority attribute to the first template directive. We add a second template directive that only matches elements named “remove” with a higher priority value.
If you change the match attribute from “remove” to “@remove”, then attributes named remove will be eliminated rather than elements. And using a match attribute of “@remove|remove” will eliminate both attributes and elements named “remove”.
If you only have a hammer, you tend to see every problem as a nail.
I try to restrain myself, but one of my more common workplace rants is:
If you start with xml and you end up with xml, then why aren’t you using xsl in between?
My colleagues commonly unmarshal xml to an object, manipulate the object, and marshal the object back to xml. The right choice when there are relatively complex manipulations in the middle. But xsl is a much better choice for simple manipulations:
Easier to review
Easier to test
Easier to modify
Easier to track change
Here’s a simple servlet that applies xsl transforms to posted request xml. First, the init method that reads in xsl tranform files located in /WEB-INF/xsl and stores the corresponding Templates objects in a HashMap (Templates are thread-safe).
// // Force use of xalan for environment.xsl: xalan:checkEnvironment() TransformerFactory factory = new org.apache.xalan.processor.TransformerFactoryImpl();
templates = new HashMap<String,Templates>(); String list = config.getInitParameter("transforms"); if ( list != null ) { String[] names = list.split("\\s*,\\s*"); for ( String name : names ) { if ( name.length() > 0 ) { try { InputStream in = getTemplateInputStream(getServletContext(),name); if ( in != null ) { Templates template = factory.newTemplates(new StreamSource(in)); templates.put( name,template ); } } catch (Exception e) { ; } } } } }
Next, a get method that returns the xsl transform whose name matches the request path information.