[xsl] Reusing XPath statements (defining once and only once)

Subject: [xsl] Reusing XPath statements (defining once and only once)
From: "Mitchell, David [CC]" <David.Mitchell@xxxxxxxxxxxxxxx>
Date: Thu, 17 Apr 2003 16:36:25 -0500
This is really a question about XSLT coding style. Is it good style to have
the same XPath appear multiple times in a stylesheet. Should I try to avoid
it, and if so, how. The details follow:

I made a simple XSLT stylesheet to modify the Tomcat server.xml file that
comes with the Java Web Services Development Pack to add a <Context> so that
the default Apache Axis webapps directory would be visible. 

As a transformation goes, it is pretty simple. Just add an element if it
isn't already there. To perform the insertion, I started off with an
identity transform and then added template to insert the Context element.

SOURCE XML:
Here is the server.xml (which on my machine is C:\jwsdp-1.1\conf):

<?xml version="1.0"?>
<Server port="8005" shutdown="SHUTDOWN" debug="0">

  <!-- Enable JMX MBeans Support -->
  <Listener  className="org.apache.catalina.mbeans.ServerLifecycleListener"
                 debug="0"/>
  <Listener
className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"
                 debug="0"/>

  <!-- ========== Global Naming Resources ========== -->
  <GlobalNamingResources>

    <!-- Absolute Pathname of the JWSDP Installation -->
    <Environment
              name="jwsdp.home"
       description="Absolute Pathname of the JWSDP Installation"
              type="java.lang.String"
             value="C:\jwsdp-1.1"/>

    <!-- Users and Groups Database -->
    <Resource name="UserDatabase" auth="Container"
       description="Users and Groups Database"
              type="org.apache.catalina.UserDatabase"/>
    <ResourceParams name="UserDatabase">
      <parameter>
        <name>factory</name>
        <value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
      </parameter>
      <parameter>
        <name>pathname</name>
        <value>conf/tomcat-users.xml</value>
      </parameter>
    </ResourceParams>

  </GlobalNamingResources>


  <!-- ========== Internal Service Providers ========== -->
  <Service name="Internal Services">

    <!-- Non-SSL Connector on Port 8081 -->
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
               port="8081" minProcessors="5" maxProcessors="75"
               enableLookups="false"
               acceptCount="10" connectionTimeout="60000" debug="0"
               scheme="http" secure="false"/>

    <!-- Internal Services Engine -->
    <Engine    name="Services Engine" defaultHost="jwsdp-services"
               debug="0">

      <!-- Internal Services Message Logger -->
      <Logger  className="org.apache.catalina.logger.FileLogger"
               directory="logs" timestamp="true"
               prefix="services_log." suffix=".txt"/>

      <!-- Internal Services Realm -->
      <Realm   className="org.apache.catalina.realm.UserDatabaseRealm"
            resourceName="UserDatabase"
                   debug="0"/>

      <!-- Internal Services Virtual Host -->
      <Host    name="jwsdp-services" appBase="jaxm-1.1.1/services" debug="0"

               unpackWARs="false">

        <!-- Insert <Context> Elements Here As Needed -->

      </Host>

    </Engine>

  </Service>


  <!-- ========= Web Services Pack Applications ========== -->
  <Service name="Java Web Services Developer Pack">

    <!-- Non-SSL Connector on Port 8080 -->
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
               port="8080" minProcessors="5" maxProcessors="75"
               enableLookups="false" redirectPort="8443"
               acceptCount="10" connectionTimeout="60000" debug="0"
               scheme="http" secure="false"/>

    <!--
         By default, an SSL HTTP/1.1 Connector is not enabled. You can
         enable an SSL HTTP/1.1 Connector on port 8443 by following the
         steps below and uncommenting the Connector that follows these
         steps. SSL support requires the following steps (see the SSL Config
         HOWTO in the Tomcat 4.0 documentation bundle for more detailed
         instructions):

         * Execute the following command:
             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
(Windows)
             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
(Unix)
           with a password value of "changeit" for both the certificate and
           the keystore itself.
    -->

    <!-- SSL Connector on Port 8443 -->
    <!--
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
               port="8443" minProcessors="5" maxProcessors="75"
               enableLookups="false"
               acceptCount="10" connectionTimeout="60000" debug="0"
               scheme="https" secure="true">
      <Factory
className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
               clientAuth="false" protocol="TLS" />
    </Connector>
    -->

    <!-- Standard Engine -->
    <Engine    name="Standard Engine" defaultHost="localhost" debug="0">

      <!-- Pack-Wide Access Logger -->
      <Valve   className="org.apache.catalina.valves.AccessLogValve"
               directory="logs" prefix="access_log." suffix=".txt"
               resolveHosts="false"/>

      <!-- Pack-Wide Message Logger -->
      <Logger  className="org.apache.catalina.logger.FileLogger"
               directory="logs" timestamp="true"
               prefix="jwsdp_log." suffix=".txt"/>

      <!-- Pack-Wide Realm -->
      <Realm   className="org.apache.catalina.realm.UserDatabaseRealm"
            resourceName="UserDatabase"
                   debug="0"/>

      <!-- Default Virtual Host -->
      <Host    name="localhost" appBase="webapps" debug="0"
unpackWARs="false">

        <!-- Insert <Context> Elements Here As Needed -->

      </Host>

    </Engine>

  </Service>

</Server>

STYLESHEET:
Here is my stylesheet (which works, but I have reservations about the
style):

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output indent="yes" />

  <xsl:template
  match="@* | * | comment() | processing-instruction() | text()">
    <xsl:copy>
      <xsl:apply-templates
      select="@* | * | comment() | processing-instruction() | text()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Host">
    <xsl:copy>
      <xsl:apply-templates select="@*" />

      <xsl:if test="@appBase='webapps'">
        <xsl:choose>
          <xsl:when test="Context[@path='/axis']" />
          <xsl:otherwise>
            <Context debug="0"
            docBase="c:\xml-axis-10\webapps\axis" path="/axis"
            reloadable="true" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:if>

      <xsl:apply-templates
      select="@* | * | comment() | processing-instruction() | text()" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>


RESULT:
And here is the result (which is OK):

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN" debug="0">

  <!-- Enable JMX MBeans Support -->
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"
debug="0"/>
  <Listener
className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"
debug="0"/>

  <!-- ========== Global Naming Resources ========== -->
  <GlobalNamingResources>

    <!-- Absolute Pathname of the JWSDP Installation -->
    <Environment name="jwsdp.home" description="Absolute Pathname of the
JWSDP Installation" type="java.lang.String" value="C:\jwsdp-1.1"/>

    <!-- Users and Groups Database -->
    <Resource name="UserDatabase" auth="Container" description="Users and
Groups Database" type="org.apache.catalina.UserDatabase"/>
    <ResourceParams name="UserDatabase">
      <parameter>
        <name>factory</name>
        <value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
      </parameter>
      <parameter>
        <name>pathname</name>
        <value>conf/tomcat-users.xml</value>
      </parameter>
    </ResourceParams>

  </GlobalNamingResources>


  <!-- ========== Internal Service Providers ========== -->
  <Service name="Internal Services">

    <!-- Non-SSL Connector on Port 8081 -->
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8081" minProcessors="5" maxProcessors="75" enableLookups="false"
acceptCount="10" connectionTimeout="60000" debug="0" scheme="http"
secure="false"/>

    <!-- Internal Services Engine -->
    <Engine name="Services Engine" defaultHost="jwsdp-services" debug="0">

      <!-- Internal Services Message Logger -->
      <Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" timestamp="true" prefix="services_log." suffix=".txt"/>

      <!-- Internal Services Realm -->
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" debug="0"/>

      <!-- Internal Services Virtual Host -->
      <Host name="jwsdp-services" appBase="jaxm-1.1.1/services" debug="0"
unpackWARs="false">

        <!-- Insert <Context> Elements Here As Needed -->

      </Host>

    </Engine>

  </Service>


  <!-- ========= Web Services Pack Applications ========== -->
  <Service name="Java Web Services Developer Pack">

    <!-- Non-SSL Connector on Port 8080 -->
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080" minProcessors="5" maxProcessors="75" enableLookups="false"
redirectPort="8443" acceptCount="10" connectionTimeout="60000" debug="0"
scheme="http" secure="false"/>

    <!--
         By default, an SSL HTTP/1.1 Connector is not enabled. You can
         enable an SSL HTTP/1.1 Connector on port 8443 by following the
         steps below and uncommenting the Connector that follows these
         steps. SSL support requires the following steps (see the SSL Config
         HOWTO in the Tomcat 4.0 documentation bundle for more detailed
         instructions):

         * Execute the following command:
             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
(Windows)
             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
(Unix)
           with a password value of "changeit" for both the certificate and
           the keystore itself.
    -->

    <!-- SSL Connector on Port 8443 -->
    <!--
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
               port="8443" minProcessors="5" maxProcessors="75"
               enableLookups="false"
               acceptCount="10" connectionTimeout="60000" debug="0"
               scheme="https" secure="true">
      <Factory
className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
               clientAuth="false" protocol="TLS" />
    </Connector>
    -->

    <!-- Standard Engine -->
    <Engine name="Standard Engine" defaultHost="localhost" debug="0">

      <!-- Pack-Wide Access Logger -->
      <Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="access_log." suffix=".txt" resolveHosts="false"/>

      <!-- Pack-Wide Message Logger -->
      <Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" timestamp="true" prefix="jwsdp_log." suffix=".txt"/>

      <!-- Pack-Wide Realm -->
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" debug="0"/>

      <!-- Default Virtual Host -->
      <Host name="localhost" appBase="webapps" debug="0" unpackWARs="false">
        <Context reloadable="true" path="/axis"
docBase="c:\xml-axis-10\webapps\axis" debug="0"/>

        <!-- Insert <Context> Elements Here As Needed -->

      </Host>

    </Engine>

  </Service>

</Server>

QUESTION:
The stylesheet works, but the XPath expressions bother me. I would like to
declare this XPath once:

@* | * | comment() | processing-instruction() | text()

and refer to it elsewhere. I tried to make it a variable, but it doesn't
seem to work. I'm probably setting myself up for a Michael Kay post telling
me that I cannot just make the syntax up as I go along. 

I'm really just trying to improve my XSLT style. I have Michael's book and
Jeni Tennison's  "On the Edge Book", so references to those are welcomed.

If you notice anything else, I'm open to any ideas.

Thanks for your guidance,

David Mitchell
david.mitchell@xxxxxxxxxxxxxxx

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread