XSLT Current Date will not render - html

I am attempting to place the current date/time into an XSLT document.
The XSLT:
<xsl:template name="global" match="/">
<body>
<h1>Feed</h1>
<div class="date"><xsl:value-of select="current-dateTime()"/></div>
<xsl:apply-templates select="products[#productCode='REMSA']"/>
</body>
</xsl:template>
When the current-dateTime() function is in place, it and anything below it will not render on the page. Anything above it will show up just fine. I get no errors, just blank space. This is day 4 of me looking at XSLT so I am very new this language. Any help, tips, or recommendations will go a long way.
Thank You!

Maybe you missed to declare the XSL function namespace to have access to the current-dateTime() function:
Add to your xsl root element the fn declaration:...:
xmlns:fn="http://www.w3.org/2005/xpath-functions"
...and change your statement to:
<xsl:value-of select="fn:current-dateTime()"/>
see also:
http://www.w3schools.com/xpath/xpath_functions.asp#datetime
Can an XSLT insert the current date?

Related

XSLT: What is the best way to apply a floating text that will display the full expression for acronyms from an external dictionary file?

I'm new to XSLT.
I need to apply floating text that displays a setting for acronyms, as soon as the mouse cursor hovers over a word that is abbreviated.
My input file is XML, and every word that should display acronyms is represented in the following format:
<abbreviation Id="E.G."/>
When the mouse cursor hovers over the word EG, the floating text will be displayed: "for example".
I thought to apply the floating text using the HTML abbr tag
And the code I wrote is:
<xsl:template match="abbreviation">
<abbr title="for example.">
<xsl:value-of select="#Id"/>
</abbr>
</xsl:template>
I want the "title" attribute to be given as a parameter the definition of the main boxes from an external file that will contain a dictionary of related abbreviations and explanations.
I would love to know how to apply my issue.
And also get ideas about the external dictionary file - what kind of file should you create? For example, I would like a good structure of the file.
Note:
I use OXYGEN EDITOR,
And I believe I can also get solutions in XSLT version 2 and 3
Suppose your external dictionary looks like:
dict.xml
<dictionary>
<entry abbr="C.V.">course of life</entry>
<entry abbr="E.G.">for example</entry>
<entry abbr="N.B.">note well</entry>
</dictionary>
You can then use a key to transform an input like:
XML
<root>
<abbreviation Id="E.G."/>
</root>
using:
XSLT 2.0 (untested)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="path-to-dictionary" select="'dict.xml'"/>
<xsl:key name="abbr-lookup" match="entry" use="#abbr" />
<xsl:template match="/root">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="abbreviation">
<abbr title="{key('abbr-lookup', #Id, document($path-to-dictionary))}">
<xsl:value-of select="#Id"/>
</abbr>
</xsl:template>
</xsl:stylesheet>
to get:
Result
<html>
<body>
<abbr title="for example">E.G.</abbr>
</body>
</html>
To understand the syntax used, read about Attribute Value Templates.
Well, XSLT does not float any text, it is a programming language to transform XML (or with XSLT 2 or 3, other input formats) to XML, (X)HTML, plain text. You seem to want to transform your XML to HTML in the hope the HTML user agent or browser displays a tooltip of the title attribute.
As for using an XML file as a secondary input file, if you have abbrvs.xml with
<root><abbr key="E.G.">for example.</abbr>...</root>
then in XSLT you can use
<abbr title="{key('abbr', #Id, doc('abbrvs.xml'))}">
<xsl:value-of select="#id"/>
</abbr>
to pull that title attribute value from the secondary input file if the XSLT declares a key
<xsl:key name="abbr" match="abbr" use="#key"/>

xslt: Use variables in select and match

I need to specify the output order from a html file to a text file. Therefore I use the xsl:apply-templates select approach.
It works ok but in order to fine tune the output of the different nodes I need a corresponding template, not just a general one. This also works ok but I need to repeat the select pattern in the match pattern for the template.
I like to define a variable that holds the pattern so it only needs to be defined once.
Below is my simplified style sheet and simplified html which does not work but gives an idea of what I want to accomplish.
Is it possible to use variables like this? I can use both xslt 1.0 and 2.0 if needed.
<xsl:stylesheet ...>
...
<xsl:variable name="first">div[#class='one']</xsl:variable>
<xsl:variable name="second">div[#class='two']</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="//$first"/>
<xsl:apply-templates select="//$second"/>
...
</xsl:template>
<xsl:template match="//$first">
<xsl:text>Custom text for class one:</xsl:text><xsl:value-of select="text()"/>
</xsl:template>
<xsl:template match="//$second">
<xsl:text>Custom text for class two:</xsl:text><xsl:value-of select="text()"/>
</xsl:template>
</xsl:stylesheet>
The html:
...
<div class="two">text from two</div>
<div class="one">text from one </div>
...
Desired output:
Custom text for class one: text from one
Custom text for class two: text from two
There is no way to use variables like that in XSLT 1 or 2. The only way would be to write a stylesheet producing a second stylesheet and execute that separately.
In XSLT 3 there are new features called static variables/parameters and shadow attributes that could help or there you could use the transform function to execute a newly generated stylesheet directly with XSLT instead of in a separate step with a host language.
But using XSLT 2 you can shorten the
<xsl:apply-templates select="//div[#class='one']"/>
<xsl:apply-templates select="//div[#class='two']"/>
to
<xsl:apply-templates select="//div[#class='one'], //div[#class='two']"/>
For completeness here is the XSLT 3 approach with two static parameters used in shadow attributes:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:param name="first" static="yes" as="xs:string" select=""div[#class='one']""/>
<xsl:param name="second" static="yes" as="xs:string" select=""div[#class='two']""/>
<xsl:template match="/*">
<xsl:apply-templates _select="//{$first}, //{$second}"/>
</xsl:template>
<xsl:template _match="{$first}">
<xsl:text>Custom text for class one:</xsl:text><xsl:value-of select="text()"/>
</xsl:template>
<xsl:template _match="{$second}">
<xsl:text>Custom text for class two:</xsl:text><xsl:value-of select="text()"/>
</xsl:template>
</xsl:stylesheet>
Variables in XSLT hold values, not fragments of expressions. (In other words, XSLT is not a macro language).
As an alternative to Martin's solution, which requires XSLT 3.0, you could consider using what are sometimes called "meta-stylesheets" - do a transformation as a pre-processing step on the stylesheet itself. You could even write the generic stylesheet to use the XSLT 3.0 syntax with shadow attributes like _match, and do an XSLT preprocessing phase to convert this to regular XSLT 1.0 or 2.0 syntax for execution.

How to get html as xml for XSLT conversion usage?

I would like to do some XSLT conversion with the HTML page with YQL. The following line is used to get HTML:
select * from html where url="http://example.com/somepage" and
xpath='//div[#class="article-text"]'
How can I apply select * from xslt where ... to the previous result?
Not sure as I haven't used YQL before, but I guess you have to go the other way round: using XSLT to get the result out of the HTML and than apply the YQL-Query to get the XML as result:
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="//div[#class='article-text']" />
</xsl:template>
<xsl:template match="div[#class='article-text']">
<articletext>
<xsl:value-of select="."/>
</articletext>
</xsl:template>
YQL query:
select * from xslt where stylesheet="url/name-of.xsl" and
url="http://example.com/somepage"
This should result in
<results>
<articletext>Text of article</articletext>
</results>
As I don't know YQL but was used working with XSLT/XPath, I just googled about it and found this recommendable SO example: YQL column projection using XPATH . Instead of just pasting the link I adjusted the XSLT-Part of the example provided there to match your query.
Note that HTML is not an XML-based language (though XHTML is). If you want to operate on HTML using XML tools, you will need to either find an HTML parser (such as nekohtml, which is based on Apache Xerces) or preconvert the HTML to XHTML using something like the W3C's tidy tool.

XSLT v1.0 - document() call external template

I am trying to access a xsl template in a different xsl file from inside my template. The 2 templates are on different XSL files and that's the reason I need the document function. The templates also apply on different xml files.
My problem is how to call the second template from inside the first one. Sample of my code:
I am inside template Library:
<xsl:template match="Library">
<fo:table table-layout="fixed" width="160mm">
<fo:table-column column-width="80mm"/>
<fo:table-column column-width="80mm"/>
<fo:table-body>
<fo:table-row>
<xsl:for-each select="document(Library/#File)/Document/Books">
<xsl:apply-templates select="."/>
</xsl:for-each>
</fo:table-row>
<fo:table-body>
</fo:table>
</xsl:template>
and I am trying to access the template Books:
<xsl:template match="Books">
<fo:table-cell>
<fo:block font-family="arial" font-size="8pt" text-align="left">
<xsl:value-of select="substring(#IBAN,4)"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-family="arial" font-size="8pt" text-align="left">
<xsl:value-of select="#date"/>
</fo:block>
</fo:table-cell>
</xsl:template>
The first argument inside the document function does not seem to be set correctly. Any thoughts on how should i rewrite it ? I couldn't find any issue in the forum having a similar problem.
Any help would be appreciated, thanks
To bring a template in from another XSLT file, use xsl:import or xsl:include. Use xsl:document when you want to apply XSLT templates to the XML found in the specified document in addition to the default input XML.
Unfortunately, you will not be able to use a variable in the path to the XSLT file because the path is resolved at compile-time.
If the path cannot be determined statically (possibly achieving the needed variation via a relative path specification), you might want to reconsider your overall organization. You could go so far as to compose your XSLT programatically before running it so as to be able to dynamically write the static #href, but do reconsider your overall solution architecture before going that far.

XSL Processing Order

I've had trouble finding an exact, and simple, answer to this question on SO or elsewhere:
In XSL files, how can you tell which template will be processed first, second, etc? I read that it was ordered by how specific the XPath was. Additionally, is there a difference in XSL 1.0 vs. 2.0?
Finally, here is a flawed XSL file I am toying with. Currently the output is just the title "Table of Contents". I'll attach the XML here as well.
<xsl:template match="/">
<h1>
<xsl:text>Table of Contents</xsl:text>
</h1>
</xsl:template>
<xsl:template match="heading1">
<h2>
<xsl:value-of select="."/>
</h2>
</xsl:template>
<p>
<xsl:text>This document contains </xsl:text>
<xsl:value-of select="count(/article/body/heading1)"/>
<xsl:text> chapters. </xsl:text>
</p>
and the XML:
<article>
<title>
Creating output
</title>
<body>
<heading1>Generating text</heading1>
<heading1>Numbering things</heading1>
<heading1>Formatting numbers</heading1>
<heading1>Copying nodes from the input document to the output</heading1>
<heading1>Handling whitespace</heading1>
</body>
Any explanation as to why all the content isn't being displayed? Thank you for your help!
Here's what's happening:
The XSLT processor reads the root element of your XML
Then it looks in the stylesheet to see what matches. It finds your first template
It executes the first template.
The first template says to output the text, and then does nothing else, so the XSLT processor moves on to the next input element.... but you've processed the entire root node, so there are no more input nodes at the same level. It's done.
What you need to do is put an <xsl:apply-templates/> inside the first template. When this is encountered by the processor, it starts over but this time the context is the list of second-level nodes inside the root. It will look at each XML node in turn, find the best matching template in your stylesheet, and execute it.
This is a key concept -- The template is NOT in control, and is not procedural.