Re: [xsl] xslt-events and questions

Subject: Re: [xsl] xslt-events and questions
From: Hermann Stamm-Wilbrandt <STAMMW@xxxxxxxxxx>
Date: Wed, 11 Apr 2012 21:03:22 +0200
Hello,

today I want to give an update
* on the problems encountered while generating the HTML page from XSLT
* demonstrate that dynamic XML really works by a rudimentary solitair0 demo

Despite being able to pass "real" XML as argument to the 2nd argument XML
string of function displayResult(...) in xslt-events.html below trying to
do
the same when creating that HTML page from XSLT fails:
No '<' is allowed in the 2nd argument of displayResult(...) because that is
part of an XSLT attribute!

The solution is to pass the XML string serialized as 2nd argument, that
works.


Since even the initial position of solitair0 will be drawn by XSLT, the
initial position HTML page is really minimal. The multiline string below
is a Javascript string where '<' is fine, but '\' at line ends is needed.
(clicking on the link will start "solitair0" demo in your browser)


http://stamm-wilbrandt.de/en/xsl-list/solitair0/draw.html
---------------------------------------------------------
<html>
<!--
     solitair0-demo: "initial position" draw.html
-->
<head>
<script src="xslt-events.js" type="text/javascript"></script>
</head>
<body onload="javascript:displayResult('draw.xsl','\
<position>                                         \
<row><f/><f/><f/><f/><f/><f/><f/><f/><f/></row>    \
<row><f/><f/><f/><p/><p/><p/><f/><f/><f/></row>    \
<row><f/><f/><f/><p/><p/><p/><f/><f/><f/></row>    \
<row><f/><p/><p/><p/><p/><p/><p/><p/><f/></row>    \
<row><f/><p/><p/><p/><h/><p/><p/><p/><f/></row>    \
<row><f/><p/><p/><p/><p/><p/><p/><p/><f/></row>    \
<row><f/><f/><f/><p/><p/><p/><f/><f/><f/></row>    \
<row><f/><f/><f/><p/><p/><p/><f/><f/><f/></row>    \
<row><f/><f/><f/><f/><f/><f/><f/><f/><f/></row>    \
</position>                                        \
')"/>
</html>


And the only 116 lines of stylesheet do the display as well as a
rudimentary
mark action (click on any of the 33 fields, and it will be marked). You can
repeat marking resulting in more and more entries getting marked. This is
not a complete solitair yet, but just a proof that the concept really works
and hopefully getting some comments on pitfalls, the attribute problem
currently there or why only IE does not allow the marking click (the
display
is fine for all big5 browsers!).


http://stamm-wilbrandt.de/en/xsl-list/solitair0/draw.xsl
--------------------------------------------------------
<!--
     solitair0-demo: draw.xsl based on xslt-events.js
-->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>
  <xsl:output method="html"/>

  <!-- include "xslt-events.js" and draw outer border -->
  <xsl:template match="/">
    <html>
    <head>
    <script src="xslt-events.js" type="text/javascript"></script>
    </head>
    <body><table border="1"><tr><td>
    <xsl:apply-templates select="position"/>
    </td></tr></table>
    </body></html>
  </xsl:template>

  <!-- draw board of fields without spacing -->
  <xsl:template match="position">
    <table cellpadding="0" cellspacing="0">
      <xsl:apply-templates select="row"/>
    </table>
  </xsl:template>

  <!-- row -->
  <xsl:template match="row">
    <tr>
      <xsl:apply-templates select="*">
        <xsl:with-param name="row" select="position()"/>
      </xsl:apply-templates>
    </tr>
  </xsl:template>

  <!-- field -->
  <xsl:template match="*">
    <xsl:param name="row"/>

    <td>
      <xsl:variable name="xml">
        <xsl:variable name="cur" select="."/>

        <xsl:apply-templates select="../.." mode="serialize-m">
          <xsl:with-param name="cur" select="$cur"/>
        </xsl:apply-templates>
      </xsl:variable>

      <xsl:choose>
        <xsl:when test="not(starts-with(local-name(.),'f'))">
          <a href="javascript:displayResult('draw.xsl','{$xml}')">
            <xsl:call-template name="img">
              <xsl:with-param name="col"
                select="substring('bw',1+((position()+$row) mod 2),1)"/>
            </xsl:call-template>
          </a>
        </xsl:when>

        <xsl:otherwise>
          <xsl:call-template name="img">
            <xsl:with-param name="col"
              select="substring('bw',1+((position()+$row) mod 2),1)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </td>
  </xsl:template>

  <!-- image based on figure name and field color $col -->
  <xsl:template name="img">
    <xsl:param name="col"/>

    <xsl:element name="img">
      <xsl:attribute name="style">display:block</xsl:attribute>
      <xsl:attribute name="border">0</xsl:attribute>
      <xsl:attribute name="src">gif/<xsl:value-of select="local-name(.)"/>
        <xsl:value-of select="$col"/>.gif</xsl:attribute>
    </xsl:element>
  </xsl:template>


  <!-- simple serializer including change of $cur to 'm' -->
  <xsl:template match="text()" mode="serialize-m"/>

  <xsl:template match="*" mode="serialize-m">
    <xsl:param name="cur" select="/.."/>

    <xsl:variable name="new">
      <xsl:choose>
        <xsl:when test="generate-id(.)=generate-id($cur)">m</xsl:when>
        <xsl:otherwise><xsl:value-of select="local-name()"/>
</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="$new"/>
    <xsl:apply-templates select="@*" mode="serialize-m"/>
    <xsl:text>&gt;</xsl:text>
      <xsl:apply-templates mode="serialize-m">
        <xsl:with-param name="cur" select="$cur"/>
      </xsl:apply-templates>
    <xsl:text>&lt;/</xsl:text>
    <xsl:value-of select="$new"/>
    <xsl:text>&gt;</xsl:text>
  </xsl:template>

<!-- no attributes yet ... -->
<!--
  <xsl:template match="@*" mode="serialize-m">
    <xsl:value-of select="local-name()"/>=
      &apos;<xsl:value-of select="string()"/>&apos;
  </xsl:template>
-->

</xsl:stylesheet>


Mit besten Gruessen / Best wishes,

Hermann Stamm-Wilbrandt
Level 3 support for XML Compiler team and Fixpack team lead
WebSphere DataPower SOA Appliances
https://www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/
----------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294


                                                                                                                                   
  From:       Hermann Stamm-Wilbrandt/Germany/IBM@IBMDE                                                                            
                                                                                                                                   
  To:         xsl-list@xxxxxxxxxxxxxxxxxxxxxx,                                                                                     
                                                                                                                                   
  Date:       04/10/2012 06:28 PM                                                                                                  
                                                                                                                                   
  Subject:    [xsl] xslt-events and questions                                                                                      
                                                                                                                                   






Hello,

I know of Michael's talk on "XSLT in the browser (XMLPrague 2011)":
http://www.youtube.com/watch?v=_eA6Br1qPA8

Saxon CE provides some features allowing to do XSLT processing based on
user
events and even allows running XSLT 2.0 on mobile devices.


I just want to do XSLT processing in the browser with events (like "onLoad"
or just '<a href="...">...</a>') and can live with a solution working fine
on
the big5 browsers (Chrome, Firefox, Internet Explorer, Opera, Safari).


I need a solution providing the XML to be transformed dynamically.
Why do I need that and cannot live with xml-stylesheet PI in stored XML
files?

For example I do want to do a game of (Peg) solitair in the browser by
XSLT:
http://en.wikipedia.org/wiki/Peg_solitaire

Generating initial position from an XML configuration file is not difficult
(see http://stamm-wilbrandt.de/en/xsl-list/solitair0/img0.gif).

Now selecting a piece to move would mark that piece in a different color,
eg. http://stamm-wilbrandt.de/en/xsl-list/solitair0/img1.gif .

Then clicking on an empty field to complete the move would result in
http://stamm-wilbrandt.de/en/xsl-list/solitair0/img2.gif .

A standard XML file approach with xml-stylesheet runs into this problem:
Even not taking the marking color into account we have 33 fields, and each
of those can have a peg on it or not resulting in 2^33 or more than 8
billion
possible configurations.
I do not have that much webspace on my private web server ... ;-)


So my idea is to have a link associated with a click for each possible
field.
The stylesheet will
* take the XML configuration to display
* generate HTML page in the browser
* display the board as defined by the configuration XML
* provide hyperlinks for each field
* those hyperlinks generate dynamic XML based on the associated field
* when clicking on a field, the dynamic XML will be transformed for new
display

First I thought on a form-post or XMLHttpRequest approach.
But for those solutions a "backend service" is needed to just return the
XML
hidden in the sent data which seems to be ugly.

Because the standard xml-stylesheet approach was not possible by argument
from
above I remembered the Javascript snippets I used in
"[xsl] support of stylesheet embedding for ALL browsers" posting:
http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/201002/msg00301.html


Basically these were:
//  "DOMParser.parseFromString() in Explorer"
//  http://www.van-steenbeek.net/?q=explorer_domparser_parsefromstring

//  "Transforming XML to XHTML in the Browser"
//  http://www.w3schools.com/xsl/xsl_client.asp
function loadXMLDoc(dname)

//  "Transforming XML to XHTML in the Browser" (modified)
//  http://www.w3schools.com/xsl/xsl_client.asp
function displayResult(xslURL, xmlStr)


So just for demoing the (new?) approach (xslt-events) I use simple
stylesheet
"squares.ext.xsl" to generate a list of square values for the input values:

Input "<ns> <n>2</n> <n>3</n> </ns>" will be transformed to
output "2<sup>2</sup>=4<br>3<sup>2</sup>=9<br>".

You can find the demo here:
http://stamm-wilbrandt.de/en/xsl-list/solitair0/xslt-events.html

Clicking on "doit1" link will execute squares.ext.xsl for 6 and 5, clicking
on "doit2" will do the same for 2, 3 and 4.


I tested this approach successfully with all big5 browsers.
I know that I have to rely on the Javascript XSLT engines, not the
browser's.


I have some questions wrt the xslt-events.* files and links below:

1) Can you think of another approach without the need of a "backend
service"?

2) Is there something which can be done to avoid the need to generate
&quot;
   in doit2 sample below (because " and ' are already used by the
Javascript
   function call in the href)?

3) In DataPower XSLT Processor we have a proprietary extension element
   dp:url-open which allows tho post XML data like this:

   <dp:url-open target="someURL" response="someType">
     <!-- XML data here will be posted to "someURL" -->
   </dp:url-open>

   How close can we come to this with xslt-events Javascript approach of
   <a href="javascript:displayResult(xslURL, xmlString)">...</a> ?



This is http://stamm-wilbrandt.de/en/xsl-list/solitair0/xslt-events.html:
-------------------------------------------------------------------------
<!--
  xslt-events.html (4/10/2012)
-->
<html>
<head>
<script src="xslt-events.js" type="text/javascript"></script>
</head>
<body>
<ul>
<li/><a href="javascript:displayResult('squares.ext.xsl','
<ns><n>6</n><n>5</n></ns>
')">doit1</a>
<li/><a href="javascript:displayResult('squares.ext.xsl','
<ns test=&quot;abc&quot;><n>2</n><n>3</n><n>4&lt;/n></ns>
')">doit2</a>
</ul>
</body>
</html>


This is http://stamm-wilbrandt.de/en/xsl-list/solitair0/xslt-events.js:
-----------------------------------------------------------------------
// xslt-events.js (4/10/2012)

//  "DOMParser.parseFromString() in Explorer"
//  http://www.van-steenbeek.net/?q=explorer_domparser_parsefromstring
if(typeof(DOMParser) == 'undefined') {
  DOMParser = function() {}
  DOMParser.prototype.parseFromString = function(str, contentType) {
    if(typeof(ActiveXObject) != 'undefined') {
      var xmldata = new ActiveXObject('MSXML.DomDocument');
      xmldata.async = false;
      xmldata.loadXML(str);
      return xmldata;
    } else if(typeof(XMLHttpRequest) != 'undefined') {
      var xmldata = new XMLHttpRequest;
      if(!contentType) {
        contentType = 'application/xml';
      }
      xmldata.open('GET', 'data:' + contentType + ';charset=utf-8,' +
encodeURIComponent(str), false);
      if(xmldata.overrideMimeType) {
        xmldata.overrideMimeType(contentType);
      }
      xmldata.send(null);
      return xmldata.responseXML;
    }
  }
}

//  "Transforming XML to XHTML in the Browser"
//  http://www.w3schools.com/xsl/xsl_client.asp
function loadXMLDoc(dname)
{
  if (window.XMLHttpRequest)
  {
    xhttp=new XMLHttpRequest();
  }
  else
  {
    xhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xhttp.open("GET",dname,false);
  xhttp.send("");
  return xhttp.responseXML;
}

//  "Transforming XML to XHTML in the Browser" (modified)
//  http://www.w3schools.com/xsl/xsl_client.asp
function displayResult(xslURL, xmlStr)
{
  // get parser
  var parser = new DOMParser();

  xml = parser.parseFromString(xmlStr, "text/xml");
  xsl = loadXMLDoc(xslURL);

  with (document) {open(); write("<div id='example'/>"); close(); }

  // code for IE
  if (window.ActiveXObject)
  {
    result=xml.transformNode(xsl);

    // display result
    document.getElementById("example").innerHTML=result;
  }
  // code for Mozilla, Firefox, Opera, etc.
  else if (document.implementation)
  {
    xsltproc = new XSLTProcessor();
    xsltproc.importStylesheet(xsl);
    result = xsltproc.transformToFragment(xml, document);

    document.getElementById("example").appendChild(result);
  }
}


Mit besten Gruessen / Best wishes,

Hermann Stamm-Wilbrandt
Level 3 support for XML Compiler team and Fixpack team lead
WebSphere DataPower SOA Appliances
https://www.ibm.com/developerworks/mydeveloperworks/blogs/HermannSW/
----------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294

Current Thread