Passing dynamics attributes to collective.xdv inline XSL - xslt

I have the following snippet in rules.xml
<!-- Fix search box to honour Plone rules-->
<replace css:theme="form#search">
<form action="http://localhost:8080/LS/search" name="form1" id="search">
<input type="text" name="SearchableText" onclick="make_blank();" onblur="keep_search();" class="search_text_style content_text2"/>
<input type="image" src="++resource++lsm/images/template/search.png" width="22" height="22" class="search_btn" />
</form>
</replace>
How one can pass dynamic attributes to XSL so that I cat set to be real URL based on the Plone site object?
I can do this by providing helper views, modify XDVTransform, etc. but I'd like to first know what's the recommended approach here.

Note that in plone.app.theming / Diazo, you'll be able to define parameters using TAL and pass them to your theme.
I think in this case, I'd just grab the actual search URL (or the home URL) from the content with an attribute value-of.

I think you need a global <xsl:param> for this.
Typically, the value of a global parameter is set by the initiator of the transformation just before the transformation is initiated. This is a recognized general way of passing to the XSLT transformation values that are not static (known at the stylesheet compilation time).
Here is an example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pUrl" select="'http://www.cnn.com'"/>
<xsl:template match="/">
<t href="{$pUrl}"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the result is:
<t href="http://www.cnn.com" />
How a global parameter value is set is implementation-dependent and varies from one XSLT processor to another. Read the documentation of your XSLT processor to get the knowledge how to do this.

Related

How to generate html with alpine.js extensions via xslt

I try to generate a single page application based on alpine.js.
The HTML should be generate form XML descriptions via XSLT.
Example for required output.
<div #notify="alert('Hello World!')">
<button #click="$dispatch('notify')">
Notify
</button>
</div>
My try to generate this via xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:template match="test">
<div>
<xsl:attribute name="#notify">
<xsl:text>alert('Hello World!')</xsl:text>
</xsl:attribute>
<button>
<xsl:attribute name="#click">
<xsl:text>$dispatch('notify')</xsl:text>
</xsl:attribute>
Notify
</button>
</div>
</xsl:template>
</xsl:stylesheet>
Imput XML:
<?xml version="1.0"?>
<test/>
Result:
Error in xsl:attribute/#name on line 8 column 39 of alpina.xsl: XTDE0850 Attribute name {#notify} is not a valid QName
I don't know alpine.js, but we see similar problems with other "XML-like" or "HTML-like" formats.
XSLT works on the XDM data model, which defines concepts such as elements and attributes, and defines rules for the content, for example rules for element and attribute names (which don't allow them to start with "#"). If you want to generate something like the output you have shown, you first need to define a representation of this content using the XDM data model. This might include a mapping from XDM attribute names to alpine attribute names (for example, you could use the XDM attribute name __notify to represent the alpine attribute name #notify).
Then (a) your stylesheet would generate an XDM attribute named __notify, and (b) you would need a custom serialization method that serialises __notify as #notify.
The Saxon serialization machinery is highly customizable. If you want to integrate this fully, you could register a SerializerFactory with the Saxon Configuration, that registers a user-defined serialization method, and uses a subclass of XmlEmitter or HtmlEmitter to customize the output. For example you could override the writeAttribute method so it outputs __notify="xxxx" as #notify="xxxx".

How to customize feedback page Dspace XMLUI?

How to customize or change the contact page of dspace 5.5 XMLUI? What files or configuration should I change?
To add additional content to the page you have two options:
One option is to customize Contact.addBody. For example:
public void addBody(Body body) throws ... {
[...]
contact.addPara("For urgent matters call 555-666-777.");
}
Use the IDE autocompletion to see what kind of elements you can add. There are equivalents to the basic HTML elements. See DRI Schema Reference to understand it better.
The other option is to add the content through an XSL file:
First, create dspace-xmlui-mirage2/src/main/webapp/xsl/aspect/artifactbrowser/contact.xsl (assuming Mirage 2 theme) with the following content:
<xsl:stylesheet
xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
xmlns:dri="http://di.tamu.edu/DRI/1.0/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="i18n dri xsl">
<xsl:output indent="yes"/>
<xsl:template match="dri:div[#id='aspect.artifactbrowser.Contact.div.contact']">
<xsl:apply-templates />
<!-- Add here any additional HTML: -->
<p>
For urgent matters call 555-666-777.
</p>
</xsl:template>
</xsl:stylesheet>
Then, add a reference at the end of dspace-xmlui-mirage2/src/main/webapp/xsl/theme.xsl:
<xsl:import href="aspect/artifactbrowser/contact.xsl"/>

XSLT - Extract and manipulate portion of XML data

The input XML:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Description><![CDATA[Audience: Andrew Reed, Senior Training Specialist, Microsoft Corporation<br/>This session is for individuals who spend significant time writing and creating documents and have some familiarity with Microsoft Word.<br/>Thanks.]]></Description>
</root>
The XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/root">
<div>
<xsl:value-of disable-output-escaping="yes" select="Description"/>
</div>
</xsl:template>
</xsl:stylesheet>
I need to add a couple of more BR tags after first occurrence of BR, that's after Audience line and before other description starts.
Can you please modify my XSLT to get the desired output?
So I want output like below:
Audience: Andrew Reed, Senior Training Specialist, Microsoft Corporation
This session is for individuals who spend significant time writing and creating documents and have some familiarity with Microsoft Word.
Thanks.
It would be nice if your input data had the <br/> elements as actual elements, instead of being escaped, so that they could be selected directly using XPath.
But since they are as they are, you can use regexp replace, relying on the assumption that they will always conform to a limited range of patterns. You will often be warned not to parse XML or HTML in general using regexps, and rightly so, because regexps aren't a general solution. But for limited uses they can be sufficient.
If I've guessed your requirements correctly, you could use something like
<xsl:value-of select="replace(Description, '<[Bb][Rr] ?/?>',
'
')"/>
That will give you the sample output you showed, as opposed to adding a couple of more BR tags after first occurrence of BR. It will tolerate some variation, e.g. <br> or <BR />.
This is assuming you can use XSLT 2.0, because replace() isn't available in 1.0. If you're limited to 1.0, please let me know.

Overwrite the variable in xsl

I just need to overwrite the variable in xsl
Example:
x=0
if x=0
then
x=3
I need to change the value of variable.
I am very new to xsl, please help me how to achieve this. This may be silly but I don't have any idea..
I just need to overwrite the variable in xsl
Example x=0 if x=0 then x=3
XSLT is a functional language and among other things this means that a variable, once defined cannot be changed.
Certainly, this fact doesn't mean that a given problem cannot be solved using XSLT -- only that the solution doesn't contain any modifications of variable values, once defined.
Tell us what is your specific problem, and many people will be able to provide an XSLT solution :)
As other comments have noted, variables in XSLT cannot be modified once they are set. The easiest way I've found to do this is to nest variables inside each other.
<xsl:variable name="initial_condition" select="VALUE"/>
Later
<xsl:variable name="modified_condition" select="$initial_condition + MODIFIER"/>
Some of our xsl has whole reams of nested calculations which really should be in the business logic which produces the source XML. Due to a period of time where there was no developer / time to add this business logic, it was added as part of the presentation layer.
It becomes extremely hard to maintain code like this, especially considering you've probably got control flow considerations to make. The variable names end up being very convoluted and readability drops through the floor. Code like this should be a last resort, it's not really what XSLT is designed for.
The <xsl:variable> in xslt is not actual a variable. Which means it can not be changed after you have defined it and you can use it like this:
lets say we have this xml with name test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<client-list>
<client>
<name>person1</name>
</client>
<client>
<name>person2</name>
</client>
<client>
<name>person3</name>
</client>
</client-list>
and we want to transform it to csv-like (comma separated values) but replacing the person1 with a hidden person with name person4. Then lets say we have this xml with name test.xsl which will be used to transform the test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="hiddenname">person4</xsl:variable>
<!-- this template is for the root tag client-list of the test.xml -->
<xsl:template match="/client-list">
<!-- for each tag with name client you find, ... -->
<xsl:for-each select="client">
<!-- if the tag with name -name- don't have the value person1 just place its data, ... -->
<xsl:if test="name != 'person1'">
<xsl:value-of select="name"/>
</xsl:if>
<!-- if have the value person1 place the data from the hiddenperson -->
<xsl:if test="name = 'person1'">
<xsl:value-of select="$hiddenname"/>
</xsl:if>
<!-- and place a comma -->
<xsl:text>,</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
the results will be
person4,person2,person3,
I hope this will help you.

Autoclose xml tag during xslt transformation

I have :
<input type="checkbox" name="idsProduct" value="{#id}"
id="form_checkbox_product_{#id}">
<xsl:if test="$x=$y">
<xsl:attribute name="checked" >checked</xsl:attribute>
</xsl:if>
</input>
and I get :
<input type="checkbox" name="idsProduct" value="26294"
id="form_checkbox_product_26294" checked="checked"></input>
I want an input tag like :
<input type="checkbox" name="idsProduct" value="26294"
id="form_checkbox_product_26294" checked="checked" />
my xsl output is :
<xsl:output
omit-xml-declaration="yes"
method="xml"
encoding="utf-8"
indent="no" />
How can I autoclose this tag?
This is similar to this question (although your problem is the direct inverse):
Using xsl:if doesn't include closing tag
There's discussion of a 'trick' here that causes the longer form of a closed element to be used, which you appear to be inadvertently using here, in a slightly different form. I suspect your problem is because you're asking the xslt to output directly to text. Outputting to an xml document first, and then serializing that should solve your problem.
Here's an extension method I used for transforming to an XmlDocument rather than a string, which you can then simply read the .OuterXml property of if you want the string equivalent; because XSLT isn't doing the outputting to text, it should treat the closed tags correctly.
public static XmlDocument Transform(this XmlDocument input, XslCompiledTransform xslt)
{
XmlDocument outDoc = new XmlDocument(input.CreateNavigator().NameTable);
using (XmlWriter xr = outDoc.CreateNavigator().AppendChild())
{
xslt.Transform(input, xr);
}
return outDoc;
}
Try removing all whitespace from between the tags:
<input type="checkbox" name="idsProduct" value="{#id}" id="form_checkbox_product_{#id}"><xsl:if test="$x=$y"><xsl:attribute name="checked" >checked</xsl:attribute></xsl:if></input>
Does that work?