Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old May 4th, 2009, 12:11 PM
Authorized User
 
Join Date: May 2009
Posts: 14
Thanks: 3
Thanked 0 Times in 0 Posts
Default Is XSLT enough to update a local xml file?

I am lookign for the right approach to do the following task.

I have to present the xml data from a file in a user friendly(tabular) format. One of the data elements is boolean(true/false) which should be presented as check boxes. Once the user modifies one or more check boxes and submits, the data should be saved back to xml file.

Basically the user will be viewing and updating only one attribute of a particular element of an xml file.

It will be a single user viewing the table of data.


Can i use xslt only to do this? DO i need to include any vbscript/javascript to achieve this functionality?
thank you.
 
Old May 4th, 2009, 12:22 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

XSLT can transform your XML to HTML that then a browser like Internet Explorer or Firefox can render. HTML has form controls like checkboxes so you can have that in the transformation result. However if you want to save data in a HTML form then the browser usually submits data over HTTP to a server where it is processed with PHP or ASP. Saving data locally from a browser is usually difficult or not possible as even script inside the HTML document does not have access to the file system, for security reasons.

One Windows you could consider writing a HTA (HTML application), that is basically a HTML document with script that is run outside of the browser's sandbox so that you have access to the file system.

Then there are solutions like XForms although I don't know how good they are at local file edits, like HTML forms they are mainly meant to submit data to a server.

So I have mentioned some options, but the short answer to your question if XSLT alone is enough to update a local XML file based on user input is no in my view.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old May 11th, 2009, 12:28 PM
Authorized User
 
Join Date: May 2009
Posts: 14
Thanks: 3
Thanked 0 Times in 0 Posts
Default

Hi thanks for the response.
I am aiming at a HTA application as this will be used by a single user on a single workstation.
I have created a HTA file, XSLT file. The hta has the following function to load the data
Code:
 function init()
   {
    var srcTree = new ActiveXObject("Msxml2.DOMDocument.5.0");
    srcTree.async=false;
    // You can substitute other XML file names here.
    srcTree.load("mbsaclioutxslt.xml");
 
    var xsltTree= new ActiveXObject("Msxml2.DOMDocument.5.0");
    xsltTree.async = false;
    // You can substitute other XSLT file names here.
    xsltTree.load("05-08-09.xslt");
 
    resTree.innerHTML = srcTree.transformNode(xsltTree);
   }
The xslt is displaying the data in a table format. One of the data attributes is a true/false value which is being diaplyed as a checkbox.

If the user updates the checkbox value of one or more of the row sets and clicks a button called SAVE at the bottom of the screen, the updated values should be saved to a local xml file.

I am able to load the data,display and save the file locally. But i am unable to get the user updates on the checkbox column. I have tried the following options
1. document.formname.fieldname.value to access the checkbox values when SAVE is clicked
2. onclick event for each checkbox to call a function
3. instead of using xslt, tried creating the html table using the document.write in body/script tag. Below is snippet of my hta file where the checkbox is being created.
Code:
  row_str = row_str & "<td><input type='checkbox' name='authorized' value='" & GUID & "' onClick='SaveData1 " & GUID & "'/></td>"
In all the cases the display and saving is fine but am unable to capture the updates to checkboxes. ANY HELP PLEASE

I can provide any other info if needed...


thanks so much
 
Old May 11th, 2009, 12:45 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I don't know anything about HTA as I tend to avoid Microsoft-proprietary technologies. However, the question seems to be general. If you want to update a file on a server then you will need to have something running on the server that enables this. The usual approach is to collect together the user's input into the HTML form fields, construct a URL with parameters which is sent to the server, and have the server run an XSLT transformation which uses these parameters to transform the XML document.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old May 11th, 2009, 01:04 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Here is an example, the stylesheet puts an XPath to the XML element into the input type="checkbox"'s name attribute, then the onclick handler simply updates the element as needed.
XML sample document:
Code:
<data>
  <item>
    <foo>true</foo>
  </item>
  <item>
    <foo>false</foo>
  </item>
  <item>
    <foo>true</foo>
  </item>
</data>
XSLT stylesheet:
Code:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  
  <xsl:output method="html" indent="yes"/>
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="data">
    <table border="1">
      <thead>
        <tr>
          <xsl:apply-templates select="item[1]/*" mode="th"/>
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates select="item"/>
      </tbody>
    </table>
  </xsl:template>
  
  <xsl:template match="item/*" mode="th">
    <th>
      <xsl:value-of select="name()"/>
    </th>
  </xsl:template>
  
  <xsl:template match="item">
    <tr>
      <xsl:apply-templates>
        <xsl:with-param name="p" select="position()"/>
      </xsl:apply-templates>
    </tr>
  </xsl:template>
  
  <xsl:template match="item/foo">
    <xsl:param name="p"/>
    <td>
      <input type="checkbox"
             name="{concat(name(..), '[', $p, ']/', name())}"
             value="{.}"
             onclick="updateCheckbox(this);">
        <xsl:if test=". = 'true'">
          <xsl:attribute name="checked">checked</xsl:attribute>
        </xsl:if>
      </input>
    </td>
  </xsl:template>

</xsl:stylesheet>
HTA code with JavaScript:
Code:
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTA test</title>
<script type="text/javascript">
var msxmlVersion = '3.0';

var doc, sheet;

function updateCheckbox(cb)
{
  doc.documentElement.selectSingleNode(cb.name).text = cb.checked ? 'true' : 'false';
}

function load()
{
  doc = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
  doc.async = false;
  doc.load('test2009051103.xml');
  doc.setProperty('SelectionLanguage', 'XPath');
  
  sheet = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
  sheet.async = false;
  sheet.load('test2009051102Xsl.xml');
  
  document.getElementById('ph1').innerHTML = doc.transformNode(sheet);
}

window.onload = load;
</script>
</head>
<body>
<h1>Example</h1>

<div id="ph1"></div>

<div>
<input type="button" value="save" onclick="doc.save('test2009051103Output.xml')">
</div>
</body>
</html>
For testing I let the HTA save to a different file than the one the data is loaded from but you could of course change that once you have everything set up as needed.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old May 11th, 2009, 04:41 PM
Authorized User
 
Join Date: May 2009
Posts: 14
Thanks: 3
Thanked 0 Times in 0 Posts
Default

Martin,
Thanks a lot for your help.

Can this be used to apply for attributes in similar fashion? I am using your samples but just wanted to check. I have to use multiple attributes from UpdateData tag with the checkbox on IsAuthorized attribute.

Can you please either point me to a reference link which i could use to update the attribute in place of
"doc.documentElement.selectSingleNode(cb.name).text = cb.checked ? 'true' : 'false';
" or how to do it?


Code:
<
Code:
Detail>
<UpdateData ID="887618" GUID="6fa81a06-fe17-4941-bb3c-de597afd29d0" BulletinID="" KBID="887618" Type="2" IsAuthorized="false" IsInstalled="true" Severity="0" RestartRequired="false">
<Title>Office 2003 Service Pack 2 for Proofing Tools</Title></UpdateData> </Detail>


As much as I wish to explore and experiment with it myself, I have just another day to finish the task on hand as i wasted one week trying to fix whatever I posted earlier today.
thanks again.
 
Old May 12th, 2009, 06:37 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

It is certainly possible to apply a similar scheme to attributes in the XML document, you just need to make sure you generate the XPath correctly.
Here is an adapted sample that makes use of the following XML:
Code:
<Detail>
<UpdateData ID="887618" GUID="6fa81a06-fe17-4941-bb3c-de597afd29d0" BulletinID="" KBID="887618" Type="2" IsAuthorized="false" IsInstalled="true" Severity="0" RestartRequired="false">
<Title>Office 2003 Service Pack 2 for Proofing Tools</Title></UpdateData> 
<UpdateData ID="2" GUID="6fa81a06-fe17-4941-bb3c-de597afd29de" BulletinID="1" KBID="887618" Type="2" IsAuthorized="true" IsInstalled="false" Severity="0" RestartRequired="false">
<Title>whatever</Title></UpdateData> 

</Detail>
Then here is an XSLT 1.0 stylesheet that transforms the XML into a HTML table where some attributes are transformed into HTML checkbox controls, some attributes and child elements into HTML text controls, and some attributes simply into readonly table cells. I have improved the XPath generation from the last sample so that it should work more generically, at least as long as namespaces do not come into play:
Code:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  
  <xsl:output method="html" indent="yes"/>
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="Detail">
    <table border="1">
      <thead>
        <tr>
          <xsl:apply-templates select="UpdateData[1]/@* | UpdateData[1]/*" mode="th"/>
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates select="UpdateData"/>
      </tbody>
    </table>
  </xsl:template>
  
  <xsl:template match="UpdateData/@* | UpdateData/*" mode="th">
    <th>
      <xsl:value-of select="name()"/>
    </th>
  </xsl:template>
  
  <xsl:template match="UpdateData">
    <tr>
      <xsl:apply-templates select="@* | *"/>
    </tr>
  </xsl:template>
  
  <!-- transform child element or attribute into checkbox -->
  <xsl:template match="UpdateData/@IsAuthorized | UpdateData/@IsInstalled">
    <xsl:variable name="xpath">
      <xsl:apply-templates select="." mode="xpath"/>
    </xsl:variable>
    <td>
      <input type="checkbox"
             name="{$xpath}"
             value="{.}"
             onclick="updateCheckbox(this);">
        <xsl:if test=". = 'true'">
          <xsl:attribute name="checked">checked</xsl:attribute>
        </xsl:if>
      </input>
    </td>
  </xsl:template>

  <!-- transform child element or attribute into readonly table cell -->
  <xsl:template match="UpdateData/@ID | UpdateData/@GUID | UpdateData/@BulletinID | UpdateData/@KBID | UpdateData/@RestartRequired">
    <td>
      <xsl:value-of select="."/>
    </td>
  </xsl:template>
  
  <!-- transform child element or attribute into input type="text" -->
  <xsl:template match="UpdateData/Title | UpdateData/@Type | UpdateData/@Severity">
    <xsl:variable name="xpath">
      <xsl:apply-templates select="." mode="xpath"/>
    </xsl:variable>
    <td>
      <input type="text"
             name="{$xpath}"
             value="{.}"
             onchange="updateText(this);"/>
    </td>
  </xsl:template>

  <xsl:template match="*" mode="xpath">
    <xsl:for-each select="ancestor::*">
      <xsl:value-of select="concat('/', name(), '[')"/>
      <xsl:number/>
      <xsl:text>]</xsl:text>
    </xsl:for-each>
  </xsl:template>
  
  <xsl:template match="@*" mode="xpath">
    <xsl:for-each select="ancestor::*">
      <xsl:value-of select="concat('/', name(), '[')"/>
      <xsl:number/>
      <xsl:text>]</xsl:text>
    </xsl:for-each>
    <xsl:value-of select="concat('/@', name())"/>
  </xsl:template>

</xsl:stylesheet>
Here is the sample HTA code, now having two functions, one for updating boolean values from a checkbox control, one for updating text elements or attributes from a text control:
Code:
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTA test</title>
<script type="text/javascript">
var xmlUrl = 'test2009051201.xml';
var xslUrl = 'test2009051201Xsl.xml';
var outputUrl = 'test2009051201Output.xml';
</script>
<script type="text/javascript">
var msxmlVersion = '3.0';

var doc, sheet;

function updateCheckbox(cb)
{
  doc.selectSingleNode(cb.name).text = cb.checked ? 'true' : 'false';
}

function updateText(input)
{
  doc.selectSingleNode(input.name).text = input.value;
}

function load()
{
  doc = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
  doc.async = false;
  doc.load(xmlUrl);
  doc.setProperty('SelectionLanguage', 'XPath');
  
  sheet = new ActiveXObject('Msxml2.DOMDocument.' + msxmlVersion);
  sheet.async = false;
  sheet.load(xslUrl);
  
  document.getElementById('ph1').innerHTML = doc.transformNode(sheet);
}

window.onload = load;
</script>
</head>
<body>
<h1>Example</h1>

<div id="ph1"></div>

<div>
<input type="button" value="save" onclick="doc.save(outputUrl);">
</div>
</body>
</html>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old May 13th, 2009, 07:07 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

The stylesheet I posted yesterday needs a slight correction to one template:
Code:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  
  <xsl:output method="html" indent="yes"/>
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="Detail">
    <table border="1">
      <thead>
        <tr>
          <xsl:apply-templates select="UpdateData[1]/@* | UpdateData[1]/*" mode="th"/>
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates select="UpdateData"/>
      </tbody>
    </table>
  </xsl:template>
  
  <xsl:template match="UpdateData/@* | UpdateData/*" mode="th">
    <th>
      <xsl:value-of select="name()"/>
    </th>
  </xsl:template>
  
  <xsl:template match="UpdateData">
    <tr>
      <xsl:apply-templates select="@* | *"/>
    </tr>
  </xsl:template>
  
  <!-- transform child element or attribute into checkbox -->
  <xsl:template match="UpdateData/@IsAuthorized | UpdateData/@IsInstalled">
    <xsl:variable name="xpath">
      <xsl:apply-templates select="." mode="xpath"/>
    </xsl:variable>
    <td>
      <input type="checkbox"
             name="{$xpath}"
             value="{.}"
             onclick="updateCheckbox(this);">
        <xsl:if test=". = 'true'">
          <xsl:attribute name="checked">checked</xsl:attribute>
        </xsl:if>
      </input>
    </td>
  </xsl:template>

  <!-- transform child element or attribute into readonly table cell -->
  <xsl:template match="UpdateData/@ID | UpdateData/@GUID | UpdateData/@BulletinID | UpdateData/@KBID | UpdateData/@RestartRequired">
    <td>
      <xsl:value-of select="."/>
    </td>
  </xsl:template>
  
  <!-- transform child element or attribute into input type="text" -->
  <xsl:template match="UpdateData/Title | UpdateData/@Type | UpdateData/@Severity">
    <xsl:variable name="xpath">
      <xsl:apply-templates select="." mode="xpath"/>
    </xsl:variable>
    <td>
      <input type="text"
             name="{$xpath}"
             value="{.}"
             onchange="updateText(this);"/>
    </td>
  </xsl:template>

  <xsl:template match="*" mode="xpath">
    <xsl:for-each select="ancestor-or-self::*">
      <xsl:value-of select="concat('/', name(), '[')"/>
      <xsl:number/>
      <xsl:text>]</xsl:text>
    </xsl:for-each>
  </xsl:template>
  
  <xsl:template match="@*" mode="xpath">
    <xsl:for-each select="ancestor::*">
      <xsl:value-of select="concat('/', name(), '[')"/>
      <xsl:number/>
      <xsl:text>]</xsl:text>
    </xsl:for-each>
    <xsl:value-of select="concat('/@', name())"/>
  </xsl:template>

</xsl:stylesheet>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
spring2009 (May 18th, 2009)
 
Old May 18th, 2009, 09:20 AM
Authorized User
 
Join Date: May 2009
Posts: 14
Thanks: 3
Thanked 0 Times in 0 Posts
Default

Hello Martin,
I used the one you have posted. I tweaked it a little bit to adjust to the root of my xml input file(only a snippet of it was used in my initial post) and adjusted the columns. It took me few hours but it worked. Thanks so much again.
 
Old May 19th, 2009, 03:38 PM
Registered User
 
Join Date: May 2009
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Exclamation Great example but have an issue with permissions

The above example is also exactly what I am looking for... however as always this is one problems. The xml and xslt seem to be working fine, but when I try to save my updates to a file via the doc.save command, I get a permission denied error. I have been researching this a while and checking my security settings but have not had any success. Any ideas on this are greatly appreciated!!





Similar Threads
Thread Thread Starter Forum Replies Last Post
how to update a xml file billbillbill XML 2 April 11th, 2007 08:23 AM
storing an xml file on to my local machine ruchilalla J2EE 0 April 28th, 2005 01:33 AM
merge two xml file and make new xml using xslt ketan XSLT 0 September 21st, 2004 08:48 AM
Merge XML files into a xml file using xslt lxu XML 4 November 6th, 2003 06:01 PM
Storing data as local file(s) (XML) planoie ASP.NET 1.0 and 1.1 Professional 0 October 31st, 2003 03:28 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.