411 REFERENCE · Wikibooks
XRX/Save File Dialog
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
Motivation
You want to allow the user to save form data into a named file in an eXist collection that will not conflict with existing files.
Method
When the user selects a Save button we will use switch/case to open up a save dialogue. In this dialogue we will list all of the current files in a collection and allow the user to create a new file with a name that does not conflict with any existing file names. If the user selects a file from the list, we will replace the current file name with that file name.
Using the get-child-resources Function
eXist provides a function that lists the files in a collection. You can get a sorted list of all the files in a collection with the following XQuery
xquery version "1.0";
declare namespace xdb="http://exist-db.org/xquery/xmldb";
declare option exist:serialize "method=xml media-type=text/xml indent=yes";
let $collection := request:get-parameter('collection', '/db/test')
return
<files>{
for $child in xdb:get-child-resources($collection)
order by lower-case($child)
return
<file>{$child}</file>
}</files>
When executed, this XQuery will return the files in a collection. For example here is the URL of an XQuery execution with the collection parameter passed as an argument:
list-files-in-collection.xq?collection=/db/rss
<files>
<file>news.rss</file>
<file>test.rss</file>
</files>
We can then use this XML listing to display a list of existing files and allow the user to select a name that is not on this list.
Sample Program
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Save File Dialog</title>
<link type="text/css" rel="stylesheet" href="save-panel.css" />
<xf:model>
<!-- This is the data that we want to save to a file on the server. -->
<xf:instance id="my-data" xmlns="">
<data>
<element1>Element 1</element1>
<element2>Element 2</element2>
<element3>Element 3</element3>
<!-- This is the file name that we are going to save the data into. -->
<filename>my-filename.xml</filename>
</data>
</xf:instance>
<!-- Placeholder for the list of files in the target collection. -->
<xf:instance xmlns="" id="list-files-results">
<data/>
</xf:instance>
<!-- This does the save. The server-side script must look for the filename element to do the save
to the correct file. -->
<xf:submission id="save" method="post" action="save.xq" ref="my-data" replace="all" />
<!-- Gets the list of current files in the server-side collection and puts them in the model. -->
<xf:submission id="list-files" method="post" action="list-files.xq" replace="instance" instance="list-files-results" />
</xf:model>
</head>
<body>
<h1>Example of Save File Panel</h1>
<xf:input ref="element1">
<xf:label>Element 1:</xf:label>
</xf:input>
<br/>
<xf:input ref="element2">
<xf:label>Element 2:</xf:label>
</xf:input>
<br/>
<xf:input ref="element3">
<xf:label>Element 3:</xf:label>
</xf:input>
<br/>
<xf:switch>
<xf:case id="default">
<xf:submit submission="save">
<xf:label>Save As...</xf:label>
<xf:toggle case="save-dialog" ev:event="DOMActivate" />
</xf:submit>
</xf:case>
<xf:case id="save-dialog">
<xf:action ev:event="xforms-select">
<xf:send submission="list-files" />
</xf:action>
<!-- This turns all the files into buttons that can be selected to select a specific file. -->
<xf:repeat nodeset="instance('list-files-results')/file" class="list-files" id="list-files-repeat">
<xf:trigger appearance="minimal">
<xf:label>
<xf:output ref="." />
</xf:label>
<xf:action ev:event="DOMActivate">
<!-- Set the filename that we will save to to the value under the selected item. -->
<xf:setvalue
ref="instance('my-data')/filename"
value="instance('list-files-results')/file[index('list-files-repeat')]" />
</xf:action>
</xf:trigger>
</xf:repeat>
<xf:input ref="instance('my-data')/filename">
<xf:label>File Name:</xf:label>
</xf:input>
<br/>
<xf:submit submission="list-files">
<xf:label>Refresh</xf:label>
</xf:submit>
<xf:submit submission="save">
<xf:label>Save</xf:label>
</xf:submit>
</xf:case>
</xf:switch>
</body>
</html>
CSS File
@namespace xf url("http://www.w3.org/2002/xforms");
body {font-family: Helvetica, sans-serif;}
.list-files {
font-size: .8em;
color: blue;
background-color: white;
border: 1px solid black;
padding: 5px;
}
Discussion
Back: Move a Resource • Next: Login and Session Management