Q on applying dyn:valuate to result tree fragment

Hermann Stamm-Wilbrandt <[email protected]> Mon, 23 Nov 2009 18:12:57 +0100
Newsgroups gmane.text.xml.xslt.extensions
Message-ID <OFB0B3F972.F3DFC36E-ONC1257677.005CF8CB-C1257677.005E91DC@de.ibm.com>
Hello,

DataPower XSLT processor provides a (propietary) extension function
"dp:url-open()" allowing to access web services from within stylesheets.

For allowing discussion I commented out that function call and replaced.
it by a variable definition containing the response (full listing at
bottom):
    <xsl:variable name="urlResponse">
      <url-open>
      <responsecode>200</responsecode>
      <content-type>text/xml</content-type>
      <headers>
      <header name="Date">Mon, 23 Nov 2009 09:04:34 GMT</header>
      <header name="Server">Apache/2.2.3 (Red Hat)</header>
      <header name="Last-Modified">Mon, 23 Nov 2009 08:57:36 GMT</header>
      <header name="ETag">"590469-36-450a000"</header>:
      <header name="Content-Type">text/xml</header></headers>
      <response>
      <RatesResponse>
      <Message>msg</Message></RatesResponse></response></url-open>
    </xsl:variable>


Customer wanted to access part of this result tree fragments response with
a dynamic XPATH expression.
    <xsl:variable name="dynPath" select="'/RatesResponse/Message'"/>

This implied the use of "dyn:evaluate()".


I came up with this "solution":
  $urlResponse is a result tree fragment.
- via the xsl:for-each loop this gets the "current node" (1 element loop)
- dyn:evaluate(concat($respPath,$dynPath)) creates XPATH expression
- xsl:apply-templates applies this XPATH
- mode "dynamic" avoids side effects


...
  <xsl:template match="*" mode="dynamic">)
    <xsl:copy-of select="."/>
  </xsl:template>
...
    <xsl:variable name="respPath" select="'/url-open/response'"/>
    <xsl:variable name="dynPath" select="'/RatesResponse/Message'"/>

    <xsl:variable name="dyn">
      <xsl:for-each select="$urlResponse">
        <xsl:copy>
          <xsl:apply-templates mode="dynamic"
            select="dyn:evaluate(concat($respPath,$dynPath))"/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:variable>

    <xsl:copy-of select="$dyn"/>
...


This works fine for DataPower as well as for XALAN XSLT processors.>
My question is just whether there is a XSLT 1.0 solution without the
xsl:for-each trick?
(motivated by this article:
http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200906/msg00070.html
)

$ curl --data-binary @some.xml http://demoip:2051; echo
<?xml version="1.0" encoding="UTF-8"?>
<Message>msg</Message>
$ java -jar xalan.jar -IN some.xml -XSL good.xsl ; echo
<?xml version="1.0" encoding="UTF-8"?><Message xmlns:exslt="
http://exslt.org/common">msg</Message>
$>


=============================================================
$ cat good.xsl
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dp="http://www.datapower.com/extensions"
  xmlns:dyn="http://exslt.org/dynamic"
  xmlns:exslt="http://exslt.org/common"
  extension-element-prefixes="dp dyn">

  <xsl:output method="xml"/>

  <xsl:template match="*" mode="dynamic">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="/">
    <xsl:variable name="someURL"
select="'http://someIp:somePort/someServlet'"/>
<!--
    <xsl:variable name="urlResponse">
      <dp:url-open target="{$someURL}" content-type="text/xml"
timeout="120" response="responsecode">
        <xsl:copy-of select="."/>
      </dp:url-open>
    </xsl:variable>>
-->
    <xsl:variable name="urlResponse">
      <url-open>
      <responsecode>200</responsecode>
      <content-type>text/xml</content-type>
      <headers>
      <header name="Date">Mon, 23 Nov 2009 09:04:34 GMT</header>
      <header name="Server">Apache/2.2.3 (Red Hat)</header>
      <header name="Last-Modified">Mon, 23 Nov 2009 08:57:36 GMT</header>
      <header name="ETag">"590469-36-450a000"</header>:
      <header name="Content-Type">text/xml</header></headers>
      <response>
      <RatesResponse>
      <Message>msg</Message></RatesResponse></response></url-open>
    </xsl:variable>

    <xsl:variable name="respPath" select="'/url-open/response'"/>>
    <xsl:variable name="dynPath" select="'/RatesResponse/Message'"/>


    <xsl:variable name="dyn">
      <xsl:for-each select="exslt:node-set($urlResponse)">
        <xsl:copy>
          <xsl:apply-templates mode="dynamic"
            select="dyn:evaluate(concat($respPath,$dynPath))"/>
        </xsl:copy>
      </xsl:for-each>
    </xsl:variable>

    <xsl:copy-of select="$dyn"/>
  </xsl:template>

</xsl:stylesheet>
$


Mit besten Gruessen / Best wishes,

Hermann Stamm-Wilbrandt
Developer, XML Compiler
WebSphere DataPower SOA Appliances
----------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294