Xforms checkbox - replacing True / False with Y / N - forms

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

Related

Orbeon/XForms: Change dropdown values based on other input control

I have a text control my-text and a dropdown my-dropdown. Depending on the content of my-text, the itemset of my-dropdown should change. Unfortunately, there is no visibility property for individual dropdown items, so I thought of a different solution. Inside the <resource xml:lang="en"> tag of my Orbeon form i defined several itemsets:
<first-itemset>
<item>
<label>AAA</label>
<value>a</value>
</item>
<item>
<label>BBB</label>
<value>b</value>
</item>
</first-itemset>
<second-itemset>
<item>
<label>XXX</label>
<value>x</value>
</item>
<item>
<label>YYY</label>
<value>y</value>
</item>
</second-itemset>
Now if content of my-text equals "first-itemset" then the first itemset should be used, otherwise the second. How can I do that?
Inside <fr:dropdown-select1 ...> I need something like
<xf:itemset ref="$form-resources/CONTENT_OF_MY-TEXT_HERE/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
What do I need to write instead of CONTENT_OF_MY-TEXT_HERE to get the actual content so orbeon uses the correct itemset?
The direct answer to your question is: *[local-name() = xxf:value('choice-control')]. So you would have:
<xf:itemset
ref="
$form-resources/
*[local-name() = xxf:value('choice-control')]/
item
">
With this, you'd get a different itemset depending the value typed in the choice control:
However, keep in mind that if you're doin this in Form Builder, your change to the source can be lost quite easily. For instance, next time you change the control name, that ref expression will be reset. So, it would be better to find another way to achieve this. For instance, you could have 2 dropdowns, of which only one is visible at any point in time, based on the value enterer in the other field.

Ektron Forms - Generate Plaintext Email

In Ektron I have a form that generates an HTML email on submission and sends it to a mailbox (foo#bar.com). An application (MailReader) checks that mailbox, reads the messages, strips all markup, and saves the resulting messages for later use. This is a problem because all the text from the HTML email end up getting mashed together and are completely unreadable by someone using the MailReader app.
For example, this HTML:
<h1>Header1</h1>
<div>
<h2>Header2</h2>
<p>Some text in a paragraph.</p>
</div>
Becomes:
Header1Header2Some text in a paragraph.
I cannot change MailReader in any way, it will always strip any markup so my solution is to have Ektron generate an email that contains no HTML for just this form. I know the email is generated using XSLT transformations with the file /Workarea/controls/forms/DefaultFormEmailBody.xslt.
My attempt at my solution involved adding a hidden input to the form with name "__nohtml". Then the XSLT will do the following:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:choose>
<xsl:when test="/field[starts-with(#name, '__nohtml')]">
<xsl:output method="text" />
</xsl:when>
<xsl:otherwise>
<xsl:output method="html" />
</xsl:otherwise>
</xsl:choose>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="/field[starts-with(#name, '__nohtml')]">
text output
</xsl:when>
<xsl:otherwise>
html output
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
But it never sends the email when I use this. I tried just rendering with this template on my own machine and I get errors. And I've also noticed that w3 documentation says the The xsl:output element is only allowed as a top-level element. That probably explains why I can't put it in the element.
I've also tried just completely omitting the element and it seems to default to HTML no matter what.
I've tried searching our local Ektron code for the point where the transformation occurs so I can tell Ektron to use the default XSLT in standard cases or use a different XSLT if __nohtml exists, but I don't know if that code is even accessible.
I would greatly appreciate it if someone can help me find a template that would allow either HTML or plaintext based on whether a field exists. If not then it would be equally awesome if someone could point me to the point of XSLT transformation in Ektron's code (if it's even accessible).
I would recommend a form strategy to generate a version of an email that you build out. There should be a public override void OnAfterSubmit(FormData formData, FormSubmittedData submittedFormData, string formXml, CmsEventArgs eventArgs) that would allow you to create pull out the submitted form data (either in the raw object or I believe it returns the xml as well. From there you could just parse it and save your html file.

Umbraco - Displaying a specific image within a macro for-each child of certain node

Umbraco newbie here. I've researched a tonne but can't seem to find what I' looking for.
I have a site with a slider on the homepage, the slider is sitting in a macro which is using a for-each (of a nodes children) with a final goal to display the 'heroImage' image from that doctype. I cant post images as a newbie to this site, but heres my content structure:
HOME
PORTFOLIO
- First Item
- Another Item
ABOUT
CONTACT US
Home, Portfolio, ABOUT and CONTACT US are "Landing Pages" document types, and the children under Portfolio (First Item and Another Item) are "Portfolio Entries" document types. Below is the code on "Landing Page" calling the Slideshow macro.
Portfolio Entry has fields:
heroImage
images
body
Slideshow macro obviously being the highlight there. Easy enough. Heres my macro code where you'll see I'm trying to display the heroImage of the node in question for each 'for-each'.
<xsl:template match="/">
<!-- slider -->
<div id="slideshow">
<div id="slider" class="nivoSlider">
<xsl:for-each select="umbraco.library:GetXmlNodeById(1081)/*[#isDoc and position() < 4]">
<xsl:variable name="mediaId" select="umbraco.library:GetMedia(#id, 'false')/data [#alias = 'umbracoFile']" />
<xsl:if test="$mediaId > 0">
<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
<xsl:if test="count($mediaNode/data) > 0 and string($mediaNode/data[#alias='umbracoFile']) != ''">
<img src="{$mediaNode/data[#alias='umbracoFile']}" alt="[image]" />
</xsl:if>
</xsl:if>
</xsl:for-each>
</div>
</div>
<!-- data-transition="slideInLeft" -->
<script type="text/javascript">
$(window).load(function() {
$('#slider').nivoSlider();
});
</script>
</xsl:template>
I feel like im so close, and ran out of search queries as most of the solutions I found were dependant on the imageId being passed onto the macro from the other side of the macro which wouldn't work.
Hope Ive explained this enough and thanks in advance for your help!
First of all, it looks like you're hardcoding the parent node id. In the code you just provided, it seems to only be getting the children of the node with id 1081. From reading what you just posted, it would seem that on all landing pages, you want to display their individual portfolio entries.
Either way, I would stay away from hardcoding IDs. If the node id changes in any way(user deletes the node, it gets exported as a package to the live environment, etc), your code will stop working. I'd just use $currentPage instead.
Judging by your filter, I imagine you only want the first 3 items to show in the slider. The code seems correct, but you seem to be using the old schema and its associated xpath. If you're using a newer version of Umbraco, the way you reference node data in xslt would have changed. I would guess that you've found many code examples and tried merging them together, without realising they wouldn't call the same schema.
This wiki link will provide more information, and hopefully fix your problem if you're using the wrong xpath.

Umbraco XSLT RenderTemplate Woes

Needing a little guidance with XSLT and Umbraco. Fairly new to XSLT but I think I understand the concepts. Right on one page I have two columns, each with their own separate pickable content. This is done via the standard content picker property (one for each column). The issue is that I need to be able to have two different templates on the page. So in essence the page navigated two which has the columns has to render two of it's child items in its own page.
I have this working with one column using a generic XSLT which I found that basically just renders what ever child item it finds, but I want it to render what ever one the user picked.
I know the Content Picker returns the XML Node ID of the page and that can be used with the Render Template function to display it (I have an example of that), but when it comes to adding in my own properties and then passing them to the RenderTemplate function I get lost. New to this XSLT :).
So far I have...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon"
xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes"
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath"
xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions"
xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings"
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:variable name="nodeID" select="data[#alias='leftColumn']"/>
<xsl:template match="/">
<xsl:value-of select="umbraco.library:RenderTemplate($nodeID)" disable-output-escaping="yes"/>
</xsl:template>
</xsl:stylesheet>
Any one know why this doesn't work and how to do what I'm after? The above gives a value was either too large or too small error.
You actually have two problems here ...
Calling RenderTemplate()
RenderTemplate actually requires two arguments when using an alternative template, the first being the content node ID, and the second being the chosen template you want applied.
<xsl:value-of
select="umbraco.library:RenderTemplate($nodeID, $templateID)"
disable-output-escaping="yes" />
See the following link for more information : http://our.umbraco.org/wiki/reference/umbracolibrary/rendertemplate
Too large or too small error
This one is simple to fix by putting an if-empty statement around the the code in question.
<xsl:if test="$nodeID != ''">
<xsl:value-of
select="umbraco.library:RenderTemplate($nodeID, $templateID)"
disable-output-escaping="yes" />
</xsl:if>
The XSLT parser likes to assume certain values are null, when in reality they aren't. Another way to get by this is to check the Skip Errors checkbox when saving, but this makes debugging actual erroneous code a bit of a pain.
Hope it helps.

How to get a part of html file?

I just want to get a part of an website within all the html-tags:
<table></table>
...
<div><font>some <b>kind</b> of <i>individual</i> text I need</font></div>
...
<div>other things I don't need</div>
-> I only want this: <font>some <b>kind</b> of <i>individual</i> text I need</font>
My goal is it to display this part with bold tags and images in a UIWebView. I've tried some XPath parser but these skipped the tags which I wanted to display in the web view.
On Stackoverflow I found a solution with java script: extract-part-of-html-in-c-objective-c but I don't know how this could help me in my ios application
Hopefully someone can help me
You may find this useful: (see the Demo inside this article)
http://api.jquery.com/html/
Its almost everything that you need, except the "make tags bold" part
update: includes getting content from separate url
http://api.jquery.com/jQuery.get/
$.get("http://www.website_i_need_to_parce.com", function(data){
/// work with "data" variable as you work with "document"
var htmlStr = data.html().find('#someDiv');
});
After this call - htmlStr will contain contents of the div with id="someDiv". If you need to paste these contents as html - use:
$('#div_on_my_site_where_I_Want_to_paste_code').text(htmlStr);
Supposing the context node is the parent of the div and the div is the first div child of the context node (You haven't provide the complete source XML !!!), this XPath expression selects the wanted nodes:
div[1]/node()
XSLT - based verification:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/t">
<xsl:copy-of select="div[1]/node()"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML fragment (wrapped into a single top node to make it a well-formed XML document):
<t>
<table></table>
...
<div>
<font>some
<b>kind</b> of
<i>individual</i> text I need
</font>
</div>
...
<div>other things I don't need</div>
</t>
the wanted, correct result is produced:
<font>some
<b>kind</b> of
<i>individual</i> text I need
</font>
Explanation: The XPath expression above selects all children nodes of the first div child of the context node. This is exactly what is wanted: all children of the div element but excluding the div element itself.