Unrecognized XSLTC extension 'http://exslt.org/common:document'' - xslt-1.0

<xsl:stylesheet version="1.0" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
<exsl:document href="filename">
<xsl:value-of select="."/>
</exsl:document>
exsl not working with XSLT 1.0, I want to create multiple files using XSLT 1.0 only. How to do it ?

I want to create multiple files using XSLT 1.0 only.
XSLT 1.0 as such does not allow for multiple result documents. You will need an XSLT 1.0 processor that either supports the EXSLT <exsl:document> element or provides a similar feature as a custom extension. Or program multiple conversions, using the calling application.

Related

XSLT for-each, trying to create header-line structure

This is not the browser type XSLT, this is for processing data (SAP B1 Integration Framework). Suppose we have two SQL Tables, HEADER and LINE and we want to avoid the kind of work where we first SELECT from the HEADER and then launch a separate select for the lines for each, because that requires "visual programming", and we like writing code more than connecting arrows. So we are sending the server a query like SELECT * FROM HEADER, SELECT * FROM LINES and we get an XML roughly like this:
<ResultSets>
<ResultSet>
<Row><MHeaderNum>1</MHeaderNum></Row>
<Row><MHeaderNum>2</MHeaderNum></Row>
<Row><MHeaderNum>3</MHeaderNum></Row>
</ResultSet>
<ResultSet>
<Row><LineNum>1</LineNum> <HeaderNum>1</HeaderNum></Row>
<Row><LineNum>2</LineNum> <HeaderNum>2</HeaderNum></Row>
<Row><LineNum>1</LineNum> <HeaderNum>3</HeaderNum></Row>
<Row><LineNum>2</LineNum> <HeaderNum>1</HeaderNum></Row>
<Row><LineNum>1</LineNum> <HeaderNum>2</HeaderNum></Row>
<Row><LineNum>2</LineNum> <HeaderNum>3</HeaderNum></Row>
</ResultSet>
so we think we are imperative, procedural programmers and pull a
<xsl:for-each select="//ResultSets/Resultset[1]/Row">
do stuff with header data
<xsl:for-each select="//ResultSets/Resultset[2]/Row[HeaderNum=MHeaderNum]">
do stiff with the line data beloning to this particular header
</xsl:for-each>
</xsl:for-each>
And of course this does not blinkin' work because MHeaderNum went out of context like grunge went out of fashion, and we cannot save it into a variable either because we will not be update that variable, as XSLT is something sort of an immutable functional programming language.
But fear not, says an inner voice, because XSLT gurus can solve things like that with templates. Templates, if I understand it, are sort of XSLT's take on functions. They can be recursive and stuff like that. So can they be used to solve problems like this?
And of course we are talking about XSLT 1.0 because I don't know whether Java ever bothered to implement the later versions, but SAP certainly did not bother to used said, hypothetical implementation.
Or should I really forget about this and just connect my visual arrows? The thing is, SQL is not supposed to be used in such an iterate through headers then iterate through lines ways. What I am trying to do is what makes an SQL database a happy, get a big ol' chunk of data out of it and then process it somewhere else, not bother it with seventy zillion tiny queries. And in our case the somewhere else is sadly XSLT, although technically I could try JavaScript as well as SAP added a Nashorn to this pile of mess as well, but maybe it is solvable in "pure" XSL?
Whether XSLT 1 or later and whether with templates and for-each, the current() function exists: //ResultSets/Resultset[2]/Row[HeaderNum=current()/MHeaderNum].
The best way to resolve cross-references is by using a key.
For example, the following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="line-by-header" match="ResultSet[2]/Row" use="HeaderNum" />
<xsl:template match="/ResultSets">
<output>
<xsl:for-each select="ResultSet[1]/Row">
<header num="{MHeaderNum}">
<xsl:for-each select="key('line-by-header', MHeaderNum)">
<line>
<xsl:value-of select="LineNum"/>
</line>
</xsl:for-each>
</header>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
when applied to the following input:
XML
<ResultSets>
<ResultSet>
<Row><MHeaderNum>1</MHeaderNum></Row>
<Row><MHeaderNum>2</MHeaderNum></Row>
<Row><MHeaderNum>3</MHeaderNum></Row>
</ResultSet>
<ResultSet>
<Row><LineNum>1</LineNum> <HeaderNum>1</HeaderNum></Row>
<Row><LineNum>2</LineNum> <HeaderNum>2</HeaderNum></Row>
<Row><LineNum>3</LineNum> <HeaderNum>3</HeaderNum></Row>
<Row><LineNum>4</LineNum> <HeaderNum>1</HeaderNum></Row>
<Row><LineNum>5</LineNum> <HeaderNum>2</HeaderNum></Row>
<Row><LineNum>6</LineNum> <HeaderNum>3</HeaderNum></Row>
</ResultSet>
</ResultSets>
will return:
Result
<?xml version="1.0" encoding="UTF-8"?>
<output>
<header num="1">
<line>1</line>
<line>4</line>
</header>
<header num="2">
<line>2</line>
<line>5</line>
</header>
<header num="3">
<line>3</line>
<line>6</line>
</header>
</output>
You can try the following XSLT. It is using three XSLT templates.
Because desired output is unknown, I placed some arbitrary processing for each of the header and line item templates.
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="/ResultSets/ResultSet[1]">
<ResultSet1>
<xsl:for-each select="Row">
<r>
<xsl:value-of select="MHeaderNum"/>
</r>
</xsl:for-each>
</ResultSet1>
</xsl:template>
<xsl:template match="/ResultSets/ResultSet[2]">
<ResultSet2>
<xsl:for-each select="Row">
<xsl:copy-of select="."/>
</xsl:for-each>
</ResultSet2>
</xsl:template>
</xsl:stylesheet>

Using Xsl <fo:external-graphic> to hand over data

Is there a way in XSL 1.0 to hand over variables or parameters using XSL fo:external-graphic like I would do when I'm using xsl:call-template
I know how I could work around the problem but I just wanted to know if there is a way I am not seeing.
If your SVGs are small enough, you could use fo:instream-foreign-object. (If the SVGs are very large, the size of the XSL-FO file might become a problem.)
main.xsl:
<xsl:import href="svg/svg_graphic.xsl" />
<xsl:template match="some/context">
<fo:instream-foreign-object>
<xsl:call-template name="make-svg">
<xsl:with-param name="param-a" select="..." />
</call-template>
</fo:instream-foreign-object>
</xsl:template>
svg_graphic.xsl:
<xsl:template name="make-svg">
<xsl:param name="param-a" select="..." />
<svg:svg>
...
</svg:svg>
</xsl:template>
<fo:external-graphic src="svg/svg_graphic.xsl" /> is not going to work. Inside your XSLT stylesheet, the elements in the XSL-FO namespace are just literal result elements. They are copied to the result tree, and they are not otherwise acted on by the XSLT processor. XSLT-specific attributes on literal result elements (where the attribute in the XSLT namespace and is defined as meaning something when used on literal result elements) are acted on by the XSLT processor. Attribute value templates ({...}) in attribute values of literal attributes (and some XSLT-defined attributes) are acted on by the XSLT processor.
There is no XSLT 1.0 way to get the XSLT processor to run another stylesheet based on the value of an XSL-FO-defined attribute.
There's also no XSLT 1.0 way to generate multiple result documents from one run of a stylesheet. Your XSLT processor probably has a processor-specific (or EXSLT) way to do that. The extension, if it exists, might not let you generate part of the XSL-FO result document, generate an SVG result document, and then go back to generating more of the XSL-FO document.

Duplicating a job in Pentaho Data Integration for different connections

I've generated a job via the Copy Tables wizard in Spoon UI, that copies some tables from an oracle database source to an SQL Server one, and made some changes to the job as well.
Now I want to duplicate the same job (same tables and same changes), but changing just the connexions. Is that possible in Spoon ?
I've looked through the Spoon UI and didn't find any option that lets me duplicate the job with changing connexions.
EDIT
After I created the two steps: one for generating rows and the other for obfuscating passwords, In the encrypted field, I do not get the 'Encrypted : Obfusctaed Password' output as expected
here is what the step generate rows looks like :
and here is an other picture for the Modified Java Script Value :
You need to make a copy of your kjb file. Jobs and transformations are in fact XML files. You can then edit it manually.
This is pretty straight-forward, with <connection> tags so you should be able to figure it all out by yourself.
I find it the fastest way if you want to keep two jobs instead of changing db connection credentials every time.
If you need to provide an obfuscated password (they are not encrypted, just obfuscated) you can create a transformation that will obfuscate it for you providing you the value to put into XML file.
Steps to reproduce creating a transformation for obfuscating passwords in Kettle 6.1 (for older versions the name of the Script Values / Mod step is Modified Java Script Value):
Step Generate rows with just 1 row storing password as value
Step Script Values / Mod for basic obfuscation
There is example in $KETTLE_HOME/samples/transformation/job-executor.
Pass connection parameters to sub-job
Bad thing u cant pass jdbc driver name so, they have to be same type of database with different connection settings
There is no way to do what you want directly from Pentaho, and one option is to directly alter the transformation's XML to change connections. So the idea is the following:
Figure out how the connection's XML will look like. For this just
register a new connection, use it somewhere in your transformation
and watch the XML source code for element like
........
Make a physical copy of your transformations
Replace connection definition and reference in the XML file. For this you may use XSLT like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- This template will replace the connection definition -->
<xsl:template match="connection[./name='SOURCE_CONNECTION_NAME']">
<!-- This is the connection configuration -->
<connection>
<name>TARGET_CONNECTION_NAME</name>
<server>localhost</server>
<type>ORACLE</type>
<access>Native</access>
<database><!-- DB NAME --> </database>
<port>1521</port>
<username><!-- USERNAME --> </username>
<password><!-- PWD --></password>
<servername/>
<data_tablespace><!-- --></data_tablespace>
<index_tablespace/>
<attributes>
<attribute><code>FORCE_IDENTIFIERS_TO_LOWERCASE</code><attribute>N</attribute></attribute>
<attribute><code>FORCE_IDENTIFIERS_TO_UPPERCASE</code><attribute>N</attribute></attribute>
<attribute><code>IS_CLUSTERED</code><attribute>N</attribute></attribute>
<attribute><code>PORT_NUMBER</code><attribute>1521</attribute></attribute>
<attribute><code>PRESERVE_RESERVED_WORD_CASE</code><attribute>Y</attribute></attribute>
<attribute><code>QUOTE_ALL_FIELDS</code><attribute>N</attribute></attribute>
<attribute><code>SUPPORTS_BOOLEAN_DATA_TYPE</code><attribute>Y</attribute></attribute>
<attribute><code>SUPPORTS_TIMESTAMP_DATA_TYPE</code><attribute>Y</attribute></attribute>
<attribute><code>USE_POOLING</code><attribute>N</attribute></attribute>
</attributes>
</connection>
</xsl:template>
<!-- And that one will replace the connection's reference in table input/table output -->
<xsl:template match="connection[text()='SOURCE_CONNECTION_NAME']">
<connection>TARGET_CONNECTION_NAME</connection>
</xsl:template>
</xsl:stylesheet>
Ah, I do believe you can do this however I have not done it myself as of yet. No need. But I believe you can use shared objects to get this kind of functionality that you want and just have the one (much easier to maintain) transformation. Here's a forum link where it's discussed.
Let me know how it works out. Pretty curious.
http://forums.pentaho.com/showthread.php?75069-Fully-Dynamic-Database-Configuration-Including-underlying-databsae-type

How costly is usage of unnecessary variables in XSLT?

It's more of a clarification that I am in need ..
as per this answer on a question, XSLT variables are cheap! My question is: Is this statement valid for all the scenarios? The instant variables which get created and get destroyed withing 4 line code aren't bothersome but loading a root node or child entities, in my opinion is indeed bad practice..
I have two XSLT files, designed for same input and output requirement:
XSLT1 (without unnecessary variable):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<Collection>
<xsl:for-each select="CATALOG/CD">
<DVD>
<Cover>
<xsl:value-of select="string(TITLE)"/>
</Cover>
<Author>
<xsl:value-of select="string(ARTIST)"/>
</Author>
<BelongsTo>
<xsl:value-of select="concat(concat(string(COUNTRY), ' '), string(COMPANY))"/>
</BelongsTo>
<SponsoredBy>
<xsl:value-of select="string(COMPANY)"/>
</SponsoredBy>
<Price>
<xsl:value-of select="string(number(string(PRICE)))"/>
</Price>
<Year>
<xsl:value-of select="string(floor(number(string(YEAR))))"/>
</Year>
</DVD>
</xsl:for-each>
</Collection>
</xsl:template>
</xsl:stylesheet>
XSLT2 (with unnecessary variable "root" in which whole XML is loaded):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="root" select="."/>
<Collection>
<xsl:for-each select="$root/CATALOG/CD">
<DVD>
<Cover>
<xsl:value-of select="string(TITLE)"/>
</Cover>
<Author>
<xsl:value-of select="string(ARTIST)"/>
</Author>
<BelongsTo>
<xsl:value-of select="concat(concat(string(COUNTRY), ' '), string(COMPANY))"/>
</BelongsTo>
<SponsoredBy>
<xsl:value-of select="string(COMPANY)"/>
</SponsoredBy>
<Price>
<xsl:value-of select="string(number(string(PRICE)))"/>
</Price>
<Year>
<xsl:value-of select="string(floor(number(string(YEAR))))"/>
</Year>
</DVD>
</xsl:for-each>
</Collection>
</xsl:template>
</xsl:stylesheet>
Approach-2 exists in realtime and infact the XML would be several KBs to few MBs, In XSLT usage of variables is extended to child entities as well..
To put-forth my proposal to change the approach, I need to verify the theory behind it..
As per my understanding incase of approach-2, system is reloading the XML data over and over in memory (incase of usage of multiple variables to load child entities the situation turns worst) and thereby slowing down the transformation process.
Before posting this question here I tested the performance of two XSLTs using timer. First approach takes few milliseconds lesser than approach-2. (I used copy-XML files to test two XSL files to avoid complexity with system cache). But again system cache might play huge confusing role here ..
Despite of this analysis of mine I still have a question in mind! Do we really need to avoid usage of variables. And as far as my system is concerned, how worthy is it to modify the realtime XSLT files, so as to use 'approach-1'?
OR Is it like XSLT variables are different than other programming languages (Incase if I'm not aware) .. Say for example, XSLT variables don't actually store the data when you do select="." but they kind of point to the data! or something like this..? AND HENCE continue using XSLT variables without hesitation..
What is your suggestion on this?
Quick Info on current system:
Host Programming Language or System: Siebel (C++ is the backend code)
XSLT Processor: Xalan (Unless Saxon is used explicitely)
I agree with the comments made that you need to measure performance with your particular XSLT processor.
But your descriptions or expectations like "approach-2, system is reloading the XML data over and over in memory" seem wrong to me. The XSLT processor builds an input tree of the primary input XML document anyway and I can't imagine that any implementation then with <xsl:variable name="root" select="."/> does anything like loading the document completely again, it would even be wrong, as node identity and generate-id would not work. The variable will simply keep a reference to the document node of the existing input tree.
Of course in your sample where you have a single input document and a single template where the current node is the document anyway the use of the variable you have is superfluous. But there are cases where you need to store the document node of the primary input document, in particular when you deal with multiple documents.

XslCompiledTransform with XSLT 1.0 ms:format-time() Timezone

I am working with an XslCompiledTransform object and try to parse a DateTime object. It works but only shows the GMT date.
When I debug the code, the object has the correct value (GMT+2)
I am using this in the XSLT:
ms:format-time(order/#orderDate, 'H:m', 'NL-nl')
The output has a two hour difference with the correct value.
Can this be solved using XSLT 1.0 and the default .Net 4 framework methods. (C#)
Edit: Can this be solved without adding code to the XSLT https://groups.google.com/d/topic/microsoft.public.xsl/1mPHhh6F62o/discussion
Edit2: Seems that more people have problems with formatting time in XSLT 1 With different timezones: http://forums.tizag.com/showthread.php?t=17429
Ok, here it the top of my XSLT:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:dt="urn:schemas-microsoft-com:datatypes"
xmlns:user="urn:my-scripts">
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="."/>
<ms:script language="C#" implements-prefix="user">
<![CDATA[
public string correctTime(DateTime dt)
{
return dt.ToLocalTime().ToString("HH:mm");
}
]]>
</ms:script>
<xsl:template match="/">
...
and further down the XSLT some HTML markup and using the method mentioned above:
<tr>
<td>Tijd:</td>
<td>
<xsl:value-of select="user:correctTime(order/#datum)"/>
</td>
</tr>
Holland has now (because of daylight saving time) GMT + 2
without the use of this method it just converted my value to GMT
So there was a 2 hour difference. The 1 hour difference we had before wasn't noticed. But because it is now 2 hour, it got to our attention :)