Dynamically updatable href links on an xform - orbeon

From the docs, XSL processor can be used to dynamically generate href links (or other HTML content):
<xhtml:tr>
<xhtml:td>
<xsl:for-each select="{instance('fr-form-instance')/form/retrievalSection/retrievalControl">
<xhtml:a href="http://somewhere/">
<xsl:value-of select="SomeData"/>
<xsl:if test="position() lt last()">
<br/>
</xsl:if>
</xhtml:a>
</xsl:for-each>
</xhtml:td>
The above is just rough example code, that href is static in above can be ignored.
The problem is this (xslt generated link text) does not get updated automatically upon instance update; how to achieve that?

XSLT processing is done once and for all when the page loads. You can see the XSLT step as a template or preprocessing step. Once that's done, XForms processes the result, and then things get dynamically updated.
You can mix XSLT and XForms this way, but it's not trivial and if you can it's probably best to avoid it.
I would try using XForms exclusively to achieve this instead, something like:
<xhtml:td>
<xforms:repeat nodeset="instance('fr-form-instance')/form/retrievalSection/retrievalControl">
<xhtml:a href="http://somewhere/">
<xforms:output value="SomeData"/>
<xhtml:br/>
</xhtml:a>
</xforms:repeat>
</xhtml:td>
If you want the href to be dynamic, use an AVT like in XSLT:
href="{expression}"
Finally, you could put the <br/> within an <xforms:group> to make it conditional, but it's probably better to use CSS in this case if you can.

Related

Stripping extra newlines in Saxon

I use Altova XMLSpy and Saxon. Saxon adds a lot of tabs and Newlines in the result file. So I added the templates (found here on stackoverflow):
<xsl:template match="*/text()[normalize-space()]">
<xsl:value-of select="normalize-space()"/>
</xsl:template>
<xsl:template match="*/text()[not(normalize-space())]" />
to the stylesheet, which neatly removed all extra white space. However, it also removed the space before and after the <i>....</i> and <q>....</q> inside a <p>:
<p>this is <i>italic</i> text</p>
So both Altova and Saxon gave me:
<p>this is<i>italic</i>text</p>
How can I solve this problem?
Use the xsl:output element to control indentation of the output. Use xsl:strip-space and xsl:preserve-space to control whitespace handling of your input.
Use templates like the two you show only as a last resort. Here, the first template is the one causing the loss of whitepace adjacent to your i elements, because the processors are doing what you told them to do, instead of what you meant to tell them to do.

Replace <c:if> and fn:toUpperCase() with JSF-tags

This example is from a book on JSF. The excercise is to refactor the following Facelets code while eliminating <c:if> and fn:toUpperCase(). Usage of <c:forEach> is allowed.
#{myBean.numbers} returns String["one","two","three"]
As the book is on JSF and not on Java, I suppose the existing Java-code is not to be touched. But I can't think of another way to do this solely in Facelets.
<c:forEach var="item" items="#{myBean.numbers}">
<c:if test="#{not fn:endsWith(item,'o')}">
#{item}
</c:if>
<c:if test="#{fn:endsWith(item,'o')}">
#{fn:toUpperCase(item)}
</c:if>
</c:forEach>
Only thing I can think of is using a converter that conditionally uses String#toUpperCase() and then I still do not understand why use of <c:forEach> should still be allowed:
<ui:repeat var="item" value="#{myBean.numbers}">
<h:outputText value="#{item}" converter="conditionalConverter"/>
</ui:repeat>
Is there a more "Facelets way" to do this (and still a need to use <c:forEach>)?
UPDATE:
Instead of <c:if> one could still use e.g. <h:outputPanel> and it's rendered-attribute, but there is still no Java-less replacement for fn:toUpperCase().
I am asking for learning purposes only. I suppose the <ui:repeat>-solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
As to <c:if>, the JSF alternative to JSTL <c:if> is the rendered attribute on any component. For example, <h:panelGroup> or <h:outputText>. Those components doesn't generate additional markup if there are no attribtues specified which should end up in HTML, like id or styleClass, otherwise they generate a <span>.
Here's an example of both:
<h:panelGroup rendered="#{not fn:endsWith(item,'o')}">
#{item}
</h:panelGroup>
<h:outputText value="#{fn:toUpperCase(item)}" rendered="#{fn:endsWith(item,'o')}" />
As to fn:toUpperCase(), JSF has no alternative. I'm not sure why you would need a JSF alternative as it's essentially not a tag, but a simple EL function which is perfectly usable in both JSTL and JSF tags. In any case, you could if necessary throw in CSS text-transform: uppercase. As this takes place entirely client side, your only problem may be the browser support.
<h:outputText value="#{item}" style="text-transform: uppercase" />
(note: this is just an example, the normal practice is to put styles in its own .css file which you load by <h:outputStylesheet>)
<h:outputText value="#{item}" styleClass="uppercased" />
I suppose the -solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
I'm a big fan of "Use the right tool for the job". Use JSTL tags to conditionally build the JSF component tree. Use JSF components to generate HTML. That's it. See also JSTL in JSF2 Facelets... makes sense?

widgetVar name collision in Primefaces in multiple cc:renderFacet

I have composite component, in which I have toolbar and datatable. I also defined facet which contains a form for manipulating data from datatable. Users define that facet for different kinds of data. Now, I have problem because I render that facet multiple times and now I have collisions for widgetVar names for Primefaces components. It is no possible to use insertChildren multiple times so I think this is only possible solution. Also I wouldn't like to force users of component to define 10 facets and write ui:include 10 times. Is there any other way to insert some facelet code in composite component, or is there any way to pass parameter to facet, and use that parameter to dynamically create widgetVar?
OK, after some time I just didn't succeeded to do what I wanted. First I had some composite component like this:
<cc:interface>
<!-- Attributes definition -->
<cc:facet name="form"/>
</cc:interface>
<cc:implementation>
<p:dialog><f:subview id="detailSubview1"><cc:renderFacet name="form"/></f:subview></p:dialog>
<p:dialog><f:subview id="detailSubview2"><cc:renderFacet name="form"/></f:subview></p:dialog>
<!-- There is some more renderFacets but this is enough -->
</cc:implementation>
If I have for example p:selectOneMenu inside the form, without any widgetVar definitions, all will be with same name for widgetVar and this is a problem.
So, I changed this completely and I will transform this composite component to ui:composition and decorate it in my page. In that case widget vars are generated as I want, with different names, because they are in different naming containers.
A widgetVar is in fact used in JavaScript to identify the component. Therefor a widgetVar must be unique in a page. You'll have to declare it yourself.
If you want to create a custom component, as I think might suit you better than ui:define/ui:include, you might want to do something like this:
Say we want to create a component that renders a p:commandButton and a h:outputText with the same value (for whatever reason). You create a XHTML page in directory [deployed-root]/resources/example, named customComponent.xhtm:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsf/composite">
<c:interface>
<c:attribute name="text" required="true" />
</c:interface>
<c:implementation>
<h:outputText value="#{cc.attrs.text}" />
<p:commandButton value="#{cc.attrs.text}" />
</c:implementation>
</html>
Then to use this in another page you'll have to define the namespace xmlns:e="http://java.sun.com/jsf/composite/example", and then you can refer to the custom component like this: <e:customComponent text="some text here"/>.
It should also be noted that it is bad practice to declare forms in custom components. This affects flexibility of use drastically since forms cannot be nested.
PrimeFaces can generate wigetVars so you don't have to.
From the 3.4 User's Guide:
<p:dialog id="dlg">
<!-- contents -->
</p:dialog>
<p:commandButton type="button" value="Show" onclick="#{p:widgetVar('dlg')}.show();"/>
This is designed to work in naming containers, so it should work just fine in composite components, <ui:repeat/>, <h:dataTable/>, etc.

Automatically create links to content in a folder

I have 2-3 HTML files created per week that will be uploaded via FTP to a folder on the web server. The files are just plain HTML having results from my local Bridge Club.
Before I go ahead and spending time creating a "fancy" solution in .Net for this I better ask if there is any built in support for this in Umbraco.
Basically I want to have a main menu item called Results, and that page should have a secondary menu with links to each .HTML file in a specific folder
Any ideas?
Cheers,
Stefan
First, make sure you put the path that the html files are being uploaded to within the umbracoReservedPaths app setting in the web.config.
Next I would create an XSLT extension (or custom function that returns an XPathNodeIterator containing each HTML file name. The method will need to build an XmlDocument that looks something like:
<files>
<file>/htmlfiles/file1.html</file>
<file>/htmlfiles/file2.html</file>
<file>/htmlfiles/file3.html</file>
</files>
Then call CreateNavigator() on the XmlDocument and return that from the XSLT extension method. Use Directory.GetFiles to get the list of HTML file names and convert them to a web ready URL like /htmlfiles/file1.html.
Then display it all with a simple XSLT macro that iterates the result of your XSLT extension in a for-each. That would look something like:
<xsl:for-each select="customExtensions:GetFiles()//file">
<a>
<xsl:attribute name="href">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:text>File #</xsl:text>
<xsl:value-of select="position()" />
</a>
</xsl:for-each>
This would generate a list like
File #1
File #2
File #3
all linking to their respective value in the xml.
A good example of an extension method is here

xslt namspace related to copying some elements

So, I have a stylesheet that spends most of its time transforming elements from 'namespace a' to the xhtml namespace.
In one particular case, however, I want to allow the input vocabulary to include any xhtml element. From a schema standpoint, I've added an <xs:any namespace="...."/> for the xhtml namespace.
It looks like:
<btml:html-noscript xmlns="http://www.w3.org/1999/xhtml">
<div style="display:inline;">
<img height="1"
width="1"
style="border-style:none;"
alt=""
src="http://www.googleadservices.com/pagead/conversion/1070015830/?label=FoKlCKDxiAIQ1sqc_gM&guid=ON&script=0"/>
</div>
</btml:html-noscript>
The stylesheet uses xsl:copy-of to copy the children of the passthrough element into the output.
Saxon-B, which I am using (last release), seems sort of stupid about the namespaces. Even though the target namespace of the entire output document is the xhtml namespace, the output looks like:
<noscript>
<div xmlns:btml="http://www.basistech.com/2010/btml/"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
style="display:inline;">
<img height="1"
width="1"
style="border-style:none;"
alt=""
src="http://www.googleadservices.com/pagead/conversion/1070015830/?label=FoKlCKDxiAIQ1sqc_gM&guid=ON&script=0"></img>
</div>
</noscript>
Note the pointless prefixes, instead of just putting out <div ...>. Note that the document element of the whole business ('html') defines xmlns="ttp://www.w3.org/1999/xhtml".
Is there any way to neaten this up?
Try whether doing <xsl:copy-of select="node()" copy-namespaces="no"/> helps (see http://www.w3.org/TR/xslt20/#copy-of). If not then please post complete samples of XML input, and XSLT stylesheet allowing us to reproduce the problem, your snippets so far do not explain where for instance the xmlns:xhtml="..." in the result snippet on the div element comes from.
From http://www.w3.org/TR/xml-names/#scoping
The scope of a namespace declaration
declaring a prefix extends from the
beginning of the start-tag in which it
appears to the end of the
corresponding end-tag, excluding the
scope of any inner declarations with
the same NSAttName part. In the case
of an empty tag, the scope is the tag
itself.
For your case, it means that "http://www.basistech.com/2010/btml/" and "http://www.w3.org/1999/xhtml" namespace URIs bound to btml an xhtml prefixes are in scope for your div element unther "http://www.w3.org/1999/xhtml" default namespace.
Of course, as suggested by #Martin Honnen's answer xsl:copy-of/#copy-namespaces with "no" as value will strip in scope namespace not actually used (i.e. in this element or its attribute's names).

Resources