Page 1 of 1

Accessing ancestral data from currentElementLocation with XSLTOperation

Posted: Tue Mar 28, 2017 7:41 pm
by hatchjk
I'm having trouble implementing an XSLTOperation for a custom framework. The purpose of this operation is to sort list items in an unordered list, according to linguistic collation rules. For this to function, I must access the document's @lang attribute, which resides on the root element. Code for the XSLT:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" xmlns:lds="http://www.lds.org/schema/lds-meta/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs saxon" version="2.0">

<xsl:param name="currentElementLocation"/>

<xsl:template match="/">
<xsl:apply-templates select="saxon:eval(saxon:expression($currentElementLocation))"/>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="ul">
<xsl:variable name="lang" select="//html/attribute::lang"/>
<xsl:variable name="collationURI">
<xsl:value-of select="concat('http://www.w3.org/2013/collation/UCA?lang=',$lang)"/>
</xsl:variable>
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="li">
<xsl:sort collation="{$collationURI}" select="lds:get-sort-key-text(string-join(*[1][not(self::ul) and not(self::ol)]/descendant::text(),''))"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:function name="lds:get-sort-key-text">
<xsl:param name="input-text"/>
<xsl:value-of select="replace($input-text,'\p{P}','')"/>
</xsl:function>

</xsl:stylesheet>
I'm not able to access the lang attribute that must be passed as a query parameter on the collationURI variable. I get a null return for that language value, so the collation fails (it collates, but without a valid language constraint, it fails to collate the text according to collation rules for that language). I recognize the need to pass the currentElementLocation parameter in order to access data in ancestral contexts from the selected list that's being transformed, but this is failing, and I'm using that technique to access the lang attribute. Any suggestions?

Re: Accessing ancestral data from currentElementLocation with XSLTOperation

Posted: Wed Mar 29, 2017 10:44 am
by Radu
Hi,

Usually in such cases it helps to know what parameters you configured for invoking your XSLTOperation when you created your custom Author action.
I will assume you set the "sourceLocation" parameter to "/*".

You can use xsl:messages to debug your XSLT stylesheet.
If you add an xsl:message in the XSLT template which matches the "ul", is it getting called? If not, it means that the HTML document you are processing has a namespace, usually http://www.w3.org/1999/xhtml so you need to either match the ul from that particular namespace:

Code: Select all

<xsl:template match="xhtml:ul" xmlns:xhtml="http://www.w3.org/1999/xhtml">
and do the same when composing the xpath for obtaining the lang attribute:

Code: Select all

<xsl:variable name="lang" select="//xhtml:html/attribute::lang" xmlns:xhtml="http://www.w3.org/1999/xhtml"/>
or simply add on the xsl:stylesheet root element a default namespace declaration:

Code: Select all


xpath-default-namespace="http://www.w3.org/1999/xhtml"
If the namespace is not the problem (your XHTML document does not have a namespace declaration on the root element) on the template which matches "/" you can add an xsl:message to log the root element:

Code: Select all

<xsl:message>MY ROOT <xsl:copy-of select="."/></xsl:message>
then invoke the action to see what the root element looks like.

Regards,
Radu

Re: Accessing ancestral data from currentElementLocation with XSLTOperation

Posted: Wed Mar 29, 2017 3:41 pm
by hatchjk
Radu,

Thanks for your reply. No namespaces are in play here, but I hadn't set sourceLocation to /* because I need the operation to function only on the unordered list selected by the user (I was accepting the default for that parameter, the element at the cursor location). By setting the sourceLocation to "/*", will that not cause the operation to affect other unordered lists besides the one selected by the user?

Jeff

Re: Accessing ancestral data from currentElementLocation with XSLTOperation

Posted: Thu Mar 30, 2017 10:48 am
by Radu
Hi Jeff,

If you let the "sourceLocation" have the default value, your XSLT stylesheet will be applied only over the XML serialization of the UL in which the caret is placed. So it will not have enough context to look up or down the entire XML document.
That's why you should use the "sourceLocation" as "/*" in order for the XSLT to get access to the entire document, keep your existing XSLT which only matches the current element using its XPath and produces the output from it and leave the "targetLocation" parameter with the default value (meaning that the current element where the caret is placed will be replaced with the result of the XSLT stylesheet).

Regards,
Radu