Are variables (var) supported in XSLTforms or betterForm? - variable-assignment

I've prepared the following XForms document based on http://www.w3.org/MarkUp/Forms/wiki/XForms_2.0#The_var_element:
<?xml-stylesheet type="text/xsl" href="../xsltforms/xsltforms.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>var-demo</title>
<xf:model>
<xf:instance>
<data xmlns="">
<PersonGivenName>Kilroy</PersonGivenName>
</data>
</xf:instance>
</xf:model>
</head>
<body>
<xf:output value="PersonGivenName"><xf:label>PersonGivenName=</xf:label></xf:output>
<xf:var name="pg_name" value="PersonGivenName"/>
<xf:output value="pg_name"><xf:label>pg_name=</xf:label></xf:output>
</body>
</html>
It is very simple: should output (I think) Kilroy twice, first read directly from the model, then putting into a variable and printing that variable.
But the output is only
PersonGivenName=Kilroy
pg_name=
I've tried this from eXist-db 2.0 and eXide version 2.0. The code above is processed by XSLTforms; omitting the first line, it's processed by betterForm - but the result is the same.
The examples after chapter "3.2.4.2 Variable Scope" in http://www.w3.org/MarkUp/Forms/wiki/XForms_2.0 suggest that a $ prefix is needed when the value of the variable is used, but both XSLTforms and betterForm throw exception on changing the last output to value="$pg_name". The code above seems to be syntactically correct, but the value of the variable is not printed out. Can anybody explain this?

Sorry, variables are not implemented yet in XSLTForms.
I frequently define a dedicated instance for "variables".
-Alain

Neither are they in betterFORM. You can use the pattern Alain describes or use a custom simple variable mechanism we've implemented before it occured in the spec:
We got a <xf:setvariable name="foo" value="bar"/> implementation. The resulting variable can then be used with the '$' notation in certain places or (more savely) by using bf:appContext('foo') XPath function.
Joern

Related

XForms: Possible to modify HTML element attribute ? (I'm using XSLTForms)

Does XForms have a mechanism for manipulating attributes of the resultant HTML?
I guess I mean emitting HTML dynamically and setting the attributes as part of that.
I know that using a xf:repeat - you can effectively emit HTML elements, but I can't work out if this would stretch to attributes?
I'm using XSLTForms as the implementation - so maybe this support hooks for Javascript to do this if there isn't a built-in way?
The reason to ask specifically - I would like to work with the audio element (and some other HTML5 elements).
Yes, it is named AVT for Attribute Value Template. As in XSLT, just wrap XPath expressions into curly braces like in <div class="proto{$myclass}">.
Thanks to the help from Alain Couthures - I was able to put together the following. Sharing in case others find it interesting.
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Podcast Player</title>
<xf:model>
<xf:instance xmlns="">
<data>
<url/>
</data>
</xf:instance>
<xf:instance id="feed" src="https://podcasts.files.bbci.co.uk/b05qqhqp.rss"/>
</xf:model>
<style><![CDATA[
* { font-family: arial; background-color:black; color: white }
]]></style>
</head>
<body>
<h1><xf:output ref="instance('feed')/channel/title"/></h1>
<blockquote><xf:output ref="instance('feed')/channel/description"/></blockquote>
<xf:select1 ref="url" appearance="full">
<xf:itemset nodeset="instance('feed')/channel/item">
<xf:label ref="title"/>
<xf:value ref="enclosure/#url"/>
</xf:itemset>
</xf:select1>
<audio src="{url}" controls="true"/>
</body>
</html>
The relevant bit to this post is the "audio" tag and in particular the "{url}" attribute template.
Here's a screenshot:
For those that wish to try this example, you'll need XSLTForms : https://en.wikibooks.org/wiki/XSLTForms , other XForms implementations are available.
Note: save the file with the extension '.xhtml' and place behind a webserver of your choice.
For instance using test HTTP servers: php, python etc.

XForms and restxq application

I am trying to create a simple interface, that will use XForms to display a button that say "Drop a Database". I then want to be able to invoke a RestXQ document called dropdatabase.xqm which is called when the button on the form is clicked. I am using BaseX. I saved my XForm in a file called onlydel.xml in the basex/webapp/static folder. I created my RestXQ program called dropdatabase.xqm and saved it to my basex/webapp folder. I have created a database called patients.
xforms: The contents of onlydel.xml is:
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<?xsltforms-options debug="yes"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<head>
<title>XFORMS IN XHTML</title>
<model xmlns="http://www.w3.org/2002/xforms" id="order-model">
<instance>
<soap xmlns="">
</soap>
</instance>
<submission action="/dropdatabase" method="post" id="s06"/>
</model>
</head>
<body>
<h2>DATABASE</h2>
<div style="float:center;">
<fieldset style="width:50%">
<xf:submit submission="s06"><xf:label>Drop A Database</xf:label></xf:submit>
</fieldset></div>
</body>
</html>
RestXQ :The contents of dropdatabase.xqm is:
module namespace _ = 'http://exquery.org/ns/restxq';
(:~
: Deletes the blog database and redirects the user to the main page.
:)
declare
%restxq:path("/dropdatabase")
%restxq:GET
function _:dropdatabase()
{
(db:drop("patients"))
};
When I run this I get the following error:
Stopped at /home/ubuntu/basex/webapp/dropdatabase.xqm, 10/13:
[XUST0001] StaticFunc expression: no updating expression allowed.
The help I need is:
Can I do something like this with the code I have written.
What is the reason for the error and a solution to eliminate the error too would be helpful
The error message seems quite clear to me: db:drop() is an updating expression and is hence not allowed at this point. You have to mark the function as an updating function by using the %updating annotation.

Xforms checkbox - replacing True / False with Y / N

I am writing a form (betterFORMs/Xforms) to be displayed to the user with a selection of checkboxes.
If a checkbox is empty the form should bind an "N" into the element. When ticked, a "Y".
I realise there are answers to this question already but I have tried all answered solutions with no luck.
The first solution I attempted to use is here - stackoverflow link
(the first solution looks good, but I have had more success with solution 2 as I am not using Orbeon)
The answer given is what I am looking for, but I am having trouble implementing this into my form. I am not using Xhtml or Orbeon and so the binding I use seems to be different to that used in the solution.) I have tried tweaking this code to fit into my form but I get a repetitive error from the xml parser every time I load the page - but it doesn't point me to anywhere related to the new code.
The next solution I have tried is found here - stackoverflow link
This answer has had the best results in my code because the checkbox values change to N when not used and when they are deselected. The problem I have with this solution is that the Y set in the form element is contained in braces - [].
output example:
<addressProof>N</addressProof><other>[Y]</other><otherText>_text_</otherText>
Here is a snippet of my form:
model:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns="http://www.w3.org/2002/06/xhtml2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
<xsl:output method="xml" />
<xsl:template match="/">
<xforms:model id="documentsChecklist">
<xforms:instance>
<actionform xmlns="">
<xforms:model id="documentsChecklist">
<xforms:instance>
<actionform xmlns="">
<detail>
<other></other>
<otherText></otherText>
</detail>
</actionform>
</xforms:instance>
<xforms:bind id="other" nodeset="/actionform/detail/other" calculate="choose(. = 'Y', ., 'N')"/>
<xforms:bind nodeset="/actionform/detail/otherBox" relevant="/actionform/detail/other ='Y'" />
</xforms:model>
form:
<div id="formBody"><br />
<xforms:select bind="other" appearance="full" align="right">
<xforms:item>
<xforms:label>Other</xforms:label>
<xforms:value>Y</xforms:value>
</xforms:item>
</xforms:select>
<xforms:input ref="/actionform/detail/otherText">
<xforms:label>Please specify:*</xforms:label>
</xforms:input>
</div>
</xsl:template>
</xsl:stylesheet>
Why does the checkbox value now get set to "[Y]" instead of "Y"? (Could it be something to do with an Array?) Thanks.
PS. I know I could do this using a boolean for each checkbox, with the checkbox value corresponding to the boolean, which in turn updates the bind value. I would rather not have to have a big block of boolean elements and binds as I have a large amount of check boxes. this solution has an example here - stackoverflow link
A select control allows you to select more than one item and I wonder if it is why the XForms implementation you are using is adding square brackets (according to specifications selected values have to be separated by a space character, which is not always very convenient by the way).
I am afraid that XForms 1.1 and XForms 2.0 require to use extra intermediate nodes and bindings. It would be useful to be able to add 2 XPath expressions for bindings: one to convert node value to control value and the other one back from control value to node value.
As a workaround, I use another extension in XSLTForms: XSLT stylesheets for converting instances.
-Alain

Creating a GeoPoint complex data type in Facebook Open Graph

I am attempting to create a GeoPoint type to my existing Object. Facebook's documentation here isn't exactly stellar - but what I went ahead and did was create a new property and named it location. I made it of type GeoPoint and required.
I then supply the following in my template:
<meta property="my-app:location:latitude" content="<%= #location.lat %>" />
<meta property="my-app:location:longitude" content="<%= #location.lng %>" />
Yet the debugger complains:
The parser's result for this metadata did not match the input metadata. Likely, this was caused by the data being ordered in an unexpected way, multiple values being given for a property only expecting a single value, or property values for a given property being mismatched. Here are the input property =>content pairs that were not seen in the parsed result: 'my-app:location:latitude => 40.134537901957735, my-app:location:longitude => -75.00853989318185'
How am I supposed to define this GeoPoint and how am I supposed to embed the lat/lng in my URL? This does not want to validate it any way I've tried.
I just ran the URL of an object I published via another app (Endomondo), but which contains GeoPoint data into the debug tool, and this is how they did it. Bear in mind it's an array in this case (it's a path for a cycle activity) so there were actually like 60 of these, but i think a single example would just be:
Meta Tag <meta property="endoapp:route:latitude" content="3x.xxxx" />
Meta Tag <meta property="endoapp:route:longitude" content="-12x.xxxx" />
Meta Tag <meta property="endoapp:route:altitude" content="0.01" />
Looking at your example, I think maybe the omitted altitude could be the problem?
Endomondo's example uses an array of points in the 'route' field, and one each for start and finish, which are endoapp:start:latitude, endoapp:start:longitude, etc
You should omit what you specified at
property="og:type", i.e. content="my-app"
if so then you should use property="location:latitude" etc (omit "my-app" prefix)

Why can't I pass a form field of type file to a CFFUNCTION using structure syntax?

I'm trying to pass a form field of type "file" to a CFFUNCTION. The argument type is "any". Here is the syntax I am trying to use (pseudocode):
<cfloop from="1" to="5" index="i">
<cfset fieldname = "attachment" & i />
<cfinvoke component="myComponent" method="attachFile">
<cfinvokeargument name="attachment" value="#FORM[fieldname]#" />
</cfinvoke>
</cfloop>
The loop is being done because there are five form fields named "attachment1", "attachment2", et al.
This throws an exception in the function:
coldfusion.tagext.io.FileTag$FormFileNotFoundException: The form field C:\ColdFusion8\...\neotmp25080.tmp did not contain a file.
However, this syntax DOES work:
<cfloop from="1" to="5" index="i">
<cfinvoke component="myComponent" method="attachFile">
<cfinvokeargument name="attachment" value="FORM.attachment#i#" />
</cfinvoke>
</cfloop>
I don't like writing code like that in the second example. It just seems like bad practice to me.
So, can anyone tell me how to use structure syntax to properly pass a file type form field to a CFFUNCTION??
In your first codesnippet the value #FORM[fieldname]# evaluates to the name of the file uploaded. So you are sending the filename to your function instead of the name of the field containing the filename.
If you want to stick with the structure notation you might use
<cfinvokeargument name="attachment" value="FORM['#fieldname#']" />
or
<cfinvokeargument name="attachment" value="FORM.#fieldname#" />
instead. I also don't think that there is anything wrong with your (working) second code example.
Edit:
It seems as if <cffile> can not evaluate the filefield if you pass the field using the struct notation, due to some auto evaluation magic of the parameter. After some further investigations I found out that passing only the name of the formfield without the form prefix would also work.
<cfinvokeargument name="attachment" value="#fieldname#" />
The filefield parameter is documented as string, containing the name of the formfield without prefix. My last approach seems more "right" to me. It would even hide the implementation a little bit more. I'm also not so much about composing scope/struct var/keys outside of a component or function and then passing it into the function. This should better be done in the function itself.