Possibility of including Java code into XSLT1.0 file from web? - java

I'm wondering, is there any possibility to include java code into my XSLT1.0 file from other source than classpath (I dont have an acces into classpath files), like github for example or some web solution
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xalan="http://xml.apache.org/xalan/java"
xmlns:test="http://github.com/user/test.java">
<xsl:output indent="yes"/>
<xsl:template match="/">
<out>
<xsl:value-of select="test:function()"/>
</out>
</xsl:template>
</xsl:stylesheet>

Related

XML Parser skips end tag after Saxon upgrade from 10.6 to 11.3

I use xslt-saxon to transform xml file. XML parser works complitly fine on Saxon 10.6 but after upgrade to Saxon-HE 11.4 it skips closing tags and read another tags as input. It only occurs if there are only spaces in between tag. If there is any letters or nothing it works fine.
<Tag0>
<Tag1>sample1</Tag1>
<Tag2> </Tag2>
<Tag3>sample2</Tag3>
</Tag0>
ends as
<Tag0 Tag1="sample1"
Tag2=" <Tag2>
<Tag3>sample2</Tag2>
"/>
xslt file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:element name="{MsgStr}message" namespace="{$msgNamespace}">
<xsl:element name="Tag1" namespace="{$Namespace}">
<xsl:attribute name="Tag2"><xsl:value-of select="*:Tag2"/></xsl:attribute>
<xsl:attribute name="Tag3"><xsl:value-of select="*:Tag3"/></xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I tried put *:Tag2/text() but without any results.
This is very strange behaviour, and it's not really possible to investigate it without a complete repro. Your example is clearly incomplete: the stylesheet contains undeclared variables, etc. I suspect a Saxon bug, if only a failure to detect and report something you are doing wrong. Please try to put together a repro (that is, everything needed for someone else to reproduce the effect) and post it at saxonica.plan.io.

How can I join 2 XML in 1 XSL

I have two .xml files which need to be joined
The first file is Song.xml as the following:
<Songs>
<Song>
<SongID>1</SongID>
<SongName>We dont talk anymore</SongName>
<Author>M-TP</Author>
<UploadBy>admin</UploadBy>
<GerneCode>1</GerneCode>
</Song>
</Songs>
and the Gerne.xml which generate from a schema
<ns2:gernes xmlns="http://www.w3.org/2001/XMLSchema/playlist" xmlns:ns2="https://xml.netbeans.org/schema/genses">
<ns2:gerne>
<GerneCode>1</GerneCode>
<GerneName>Pop</GerneName>
<Image>img-pop.jpg</Image>
</ns2:gerne>
</ns2:gerne>
I want to join these .xml files inside a XSL, to which will add the GerneName for every Song that match the GerneName inside the Gerne.xml.
The result im trying to get should be like this:
<Songs>
<Song>
<SongID>1</SongID>
<SongName>We dont talk anymore</SongName>
<Author>M-TP</Author>
<UploadBy>admin</UploadBy>
<GerneName>Pop</GerneName>
<GerneCode>1</GerneCode>
</Song>
</Songs>
Can anyone help me with this? Any e.g or keywords what should I look up for this problem?
Assuming you are limited to XSLT 1.0, you can do:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pl="http://www.w3.org/2001/XMLSchema/playlist"
xmlns:ns2="https://xml.netbeans.org/schema/genses"
exclude-result-prefixes="pl ns2">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lookup-path" select="'Gerne.xml'" />
<xsl:key name="genre" match="ns2:gerne" use="pl:GerneCode" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GerneCode">
<xsl:variable name="code" select="." />
<!-- switch context to the other file -->
<xsl:for-each select="document($lookup-path)">
<GerneCode>
<xsl:value-of select="key('genre', $code)/pl:GerneName" />
</GerneCode>
</xsl:for-each>
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
This is assuming you are telling your XSLT processor to process the Song.xml file, and passing the path to the Gerne.xml file as a parameter.
Note that the Gerne.xml document you have posted is not well-formed XML (no </ns2:gernes> closing tag).
BTW, the correct term is "genre" - not "gerne" or "gense".

Pass absolute file path from java code to xslt document()

In my xslt I'd like to look up an xml file. I need to pass the path to this file from java code.I have the followings:
...
Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
transformer.setParameter("mypath", "/home/user/repository");
xslt:
<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="mypath"/>
...
<xsl:template match="connection[#id]">
<xsl:variable name="lookupStore" select="document('$mypath/myfile.xml')/connections"/>
<xsl:copy>
<xsl:apply-templates select="$lookupStore">
<xsl:with-param name="current" select="."/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
...
<xsl:transform>
The problem is that I want to pass an absolute "base" path to the xsl, which I want to combine with the actual xml file name (myfile.xml). It seems to me that document considers file parameters relative to the location of the xsl.
Furthermore I remarked that the parameter is not picked up from the java code. I use JABX with the default Xalan XSLT processor (1.0)
I tried many variations of passing the parameters based on the other SO posts, but no success.
You need to construct a string then with the complete file URL: document(concat('file://', $mypath, '/myfile.xml')).

Calling dateNow() with XALAN

am using XSL which is being called by JAVA method, I have tried to fix it by giving absolute path of a class but I don't think it will work because I didn't find anywhere calling a method in XSL using absolute class path so am trying by keeping in the server environment.here is my code,i have given class path and i have called method also .. but am not getting the proper output. Is this the correct way to call a method?
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:datetime="java:com.ibm.date"
exclude-result-prefixes="xalan"
version="1.0">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes" indent="no" />
<xsl:strip-space elements="*" />
<xsl:template name="RootToAcknowledgeInventoryRequirement">
<xsl:param name="Root" />
<xsl:variable name="PromiseHeader" select="$Root/PromiseHeader" />
<xsl:variable name="today" select="datetime:dateNow()" />
<xsl:variable name="OrganizationCode">
<xsl:value-of select="$PromiseHeader/#OrganizationCode" />
</xsl:variable>
<_inv:AcknowledgeInventoryRequirement releaseID="">
<_wcf:ApplicationArea>
<oa:CreationDateTime xsi:type="udt:DateTimeType">
<xsl:value-of select="datetime:dateNow()" />
</oa:CreationDateTime>
</_wcf:ApplicationArea>
As you have mentioned XLAN processor, its version is XSLT 1.0.
So by default it doesn't possess any date-time function that brings it a current datetime value.
It is XSLT 2.0 that supports
<xsl:value-of select="current-dateTime()"/>
<xsl:value-of select="current-date()"/>
<xsl:value-of select="current-time()"/>
you should go with Machael Kay's Saxon latest version for that.
Now for work around, EXSLT has been into good practice:
Download code from this link, copy date.xsl to your xsl file's location. Import it in your xsl.
<xsl:stylesheet version="1.0"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date"
...>
<xsl:import href="date.xsl" />
<xsl:template match="//root">
<xsl:value-of select="date:date-time()"/>
</xsl:template>
</xsl:stylesheet>
solution 2: Pass Datetime value as param to XSL. Use it as variable wherever required.

Delete XSL output file generation at runtime

I am writing text output files reading an XML file using XSL.
Here i am trying to check weather a particular content is available in the source XML and write that content to a file if available.
But if the content is not available ( not fulfilling "<XSL:if>" condition), then output file would be an empty file.
So I want to add an else condition and in that else condition to avoid XSL output file being created at runtime.
Any body having any clue?
<xsl:message terminate="yes"> wont help because it does generate the output but only terminating the further processing of XSL.
Can any body help or even suggest any other approach to be taken in java code even without deleting files after they have created. [By reading them and identifying empty files]
Currently I am using java to read the created empty files and delete them explicitly. Thanks in adavance.
I will give two examples how this can be done -- the second is what I recommend:
Suppose we have this XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
and we want to produce another one from it, in which the num elements with even numbers are "deleted".
One way of doing this is:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<nums>
<xsl:apply-templates/>
</nums>
</xsl:template>
<xsl:template match="num">
<xsl:choose>
<xsl:when test=". mod 2 = 1">
<num><xsl:value-of select="."/></num>
</xsl:when>
<!-- <xsl:otherwise/> -->
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The wanted result is produced:
<nums>
<num>01</num>
<num>03</num>
<num>05</num>
<num>07</num>
<num>09</num>
</nums>
Do notice: For "not doing anything" you even don't need the <xsl:otherwise> and it is commented out.
A better solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num[. mod 2 = 0]"/>
</xsl:stylesheet>
This produces the same correct result.
Here we are overriding the identity rule with a template matching num elements with even value and with empty body -- which does the "delete".
Do notice:
Here we don't use any "if-then-else" explicit instructions at all -- just Xtemplate pattern matching, which is the most distinguishing feature of XSLT.

Categories

Resources