Java Function in XSLT Transformation - java

I have this tag on XML that I need use LUHN Algoritm input xml:
<?xml version="1.0" encoding="UTF-8"?>
<tag>urn:epc:id:sgtin:0614141.100013.000000000001</tag>
I have the java code read:
public class Luhn {
public static String calculateCheckDigit(String card) {
.....
}
The code is runing perfect but now I need call the function calculateCheckDigits inside XSLT to make the transformation:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="java:sumCheck.Luhn">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xmlLuhn>
<xsl:variable name="digits" select="."/>
Variable Digits:urn:epc:id:sgtin:0614141.100013.000000000001
<xsl:variable name="Luhn13Digits" select="translate(concat('0',substring($digits,19,13)),'.','')"/>
Variable Luhn13Digits = 00614141100013
<xmlLuhn2>
<xsl:value-of select="java:calculateCheckDigit($Luhn13Digits)"/>
</xmlLuhn2>
</xmlLuhn>
</xsl:template>
It´s not working, do you have idea how to make it ?
I already import the .jar of Luhn on the xslt project in Eclipse but nothing happens.

Related

How can I pass a parameter from a java method to specific xml tag

Can you please share a way to update a value in xml tag, which is passed from a java method
Pass the values from a method to a specific xml tag. Below is a sample code;
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<company>
<staff >
<name>value1</name>
<location>value2</location>
</staff>
<company>
public class Populate{
public void populateData (String value1, String value2){
???
}
}
You could invoke an XSLT transformation from the Java application:
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:param name="newValue"/>
<xsl:template match="specific-tag">
<xsl:copy>
<xsl:value-of select="$newValue"/>
</xsl:copy>
</xsl:template>
</xsl:transform>

XSLT to pick specific nodes, and parameterizing it from Java

I have an XML structure like this,
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<PackageHeader>yadda yadda </PackageHeader>
<PackageBody>
<Element1>foo</Element1>
<Element2>bar</Element2>
<ElementN>xyz</ElementN>
</PackageBody>
I have a requirement where I need to eliminate either Element1, Element2, or ElementN, so I wrote this XSLT,
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()[not(self::Element1)][not(self::Element2)]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I am running this via a simple Java XSL Transformation program. The transformed XML has only elevrything from the orignal XML minus Element1 & Element2. I tried many ways to pass parameters from the Java program to parameterize which nodes should be eliminated, but no luck so far. Any help would be much appreciated.
Sounds like a task for XSLT 3 with static parameters and shadow attributes, best used with the Saxon s9api (http://saxonica.com/html/documentation9.9/javadoc/index.html) if that is the processor used:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="element-to-be-removed" static="yes" as="xs:string" select="'Element2'"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template _match="{$element-to-be-removed}"/>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gVhEaiE

Splitting an xml based on the contents of xml either using java or xslt

I have a requirement,consider the below xml data
Input1.xml
<Envelope>
<Notification>
<Data>
<Input>ABCDEFGHIJKLMN</Input>
<Output>RESPONSEDATA</Output>
</Data>
<Data>
<Input>OPQRSTUVWXYZ</Input>
<Output>NEXTDATA</Output>
</Data>
<Data>
<Input>ALPHABETS</Input>
<Output>SOMEDATA</Output>
</Data>
</Notification>
</Envelope>
Now I want 3 output xmls with the response as shown below the file name to have first 6 characters ofABCDEFGHIJKLMN as output file name to have as shown below
(FILE1)->ABCDEF.XML
<Output>RESPONSEDATA</Output>
(FILE2)->OPQRST.XML
<Output>NEXTDATA</Output>
(FILE3)->ALPHAB.XML
<Output>SOMEDATA</Output>
Which XSLT 1.0 processor do you use? Xalan Java supports
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:redirect="http://xml.apache.org/xalan/redirect"
extension-element-prefixes="redirect"
exclude-result-prefixes="redirect">
<xsl:template match="/Envelope/Notification/Data[not(Input/*)]">
<redirect:write select="concat(substring(Input, 1, 6), '.xml')">
<xsl:copy-of select="Output"/>
</redirect:write>
</xsl:template>
<xsl:template match="/Envelope/Notification/Data[Input/*]">
<redirect:write select="concat(local-name(Input/*), '.xml')">
<xsl:copy-of select="Output"/>
</redirect:write>
</xsl:template>
</xsl:stylesheet>
Use the solution described in Your Previous Question you can then create 3 xslt files as follow, and apply the same xml input one for each xslt/output. Explain:
<xsl:copy-of select="/Envelope/Notification/Data[child::Output/text()='RESPONSEDATA']"/>
is saying, copy all "/Envelope/Notification/Data" and it content, but only for the child Output with a text value of 'RESPONSEDATA'.
ExtractResponseData.xslt
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="/Envelope/Notification/Data[child::Output/text()='RESPONSEDATA']"/>
</xsl:template>
</xsl:stylesheet>
ExtractNextData.xslt
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="/Envelope/Notification/Data[child::Output/text()='NEXTDATA']"/>
</xsl:template>
</xsl:stylesheet>
ExtractSomeData.xslt
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="/Envelope/Notification/Data[child::Output/text()='SOMEDATA']"/>
</xsl:template>
</xsl:stylesheet>

Mapping two sources to one output

I want to performs XSLT on two sources.
Sourch_1.xml:
<Root>
<record>
<PolicyNumber>1</PolicyNumber>
<FirdsName>aa</FirdsName>
<LastName>aa</LastName>
</record>
<record>
<PolicyNumber>2</PolicyNumber>
<FirdsName>bb</FirdsName>
<LastName>bb</LastName>
</record>
Sourch_2.xml:
<Root>
<record>
<policy>
<PolicyNumber>1</PolicyNumber>
<city>aaCity</city>
<street>aaStreet</street>
</policy>
<policy>
<PolicyNumber>2</PolicyNumber>
<city>bbCity</city>
<street>bbStreet</street>
</policy>
</record>
I want the output to create tags which combine data from two sources based on PolicyNumber.
I want my output to be:
output.xml:
<Root>
<record_data>
<PolicyNumber>1</PolicyNumber>
<FirdsName>aa</FirdsName>
<LastName>aa</LastName>
<city>aaCity</city>
<street>aaStreet</street>
</record_data>
<record_data>
<PolicyNumber>2</PolicyNumber>
<FirdsName>bb</FirdsName>
<LastName>bb</LastName>
<city>bbCity</city>
<street>bbStreet</street>
</record_data>
How can i accomplish that using XSLT?
To process more than one XML input file, use the document() function. Make sure that additional XML files are in the folder where you put the XSLT stylesheet, too.
The line that deserves your attention is the following:
<xsl:for-each select="document('double2.xml')/root/record/policy[./PolicyNumber=current()/PolicyNumber]">
To begin with, document('double2.xml') opens the second XML file (I have dubbed it "double2.xml"). For the policy elements in this second XML file it checks whether their PolicyNumber is equal to the PolicyNumber of the record element from the first XML file that is being processed
I have slightly modified your input to make it well-formed (lowercased the root element and added its closing tag). Note that there is also a typo in it and you probably meant to write "FirstName" instead of "FirdsName".
Stylesheet
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="record">
<record_data>
<xsl:copy-of select="*"/>
<xsl:for-each select="document('double2.xml')/root/record/policy[./PolicyNumber=current()/PolicyNumber]">
<xsl:copy-of select="city|street"/>
</xsl:for-each>
</record_data>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record_data>
<PolicyNumber>1</PolicyNumber>
<FirdsName>aa</FirdsName>
<LastName>aa</LastName>
<city>aaCity</city>
<street>aaStreet</street>
</record_data>
<record_data>
<PolicyNumber>2</PolicyNumber>
<FirdsName>bb</FirdsName>
<LastName>bb</LastName>
<city>bbCity</city>
<street>bbStreet</street>
</record_data>
</root>
Something like below will work for you.
NOTE : I have not ran this code. where I check not(policy) you might do some change in xpath like not(./policy)
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Root/record">
<xsl:choose>
<xsl:when test="not(policy)">
<record_data>
<PolicyNumber><xsl:value-of select="PolicyNumber"/></PolicyNumber>
<FirdsName><xsl:value-of select="FirdsName"/></FirdsName>
<LastName><xsl:value-of select="LastName"/></LastName>
<city><xsl:value-of select="city"/></city>
<street><xsl:value-of select="street"/></street>
</record_data>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
<record_data>
<PolicyNumber><xsl:value-of select="policy/PolicyNumber"/></PolicyNumber>
<FirdsName><xsl:value-of select="policy/FirdsName"/></FirdsName>
<LastName><xsl:value-of select="policy/LastName"/></LastName>
<city><xsl:value-of select="policy/city"/></city>
<street><xsl:value-of select="policy/street"/></street>
</record_data>
</xsl:choose>
</xsl:for-each>

Embedding XSL Stylesheet into XML

I have the following XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="http://www.fakedomain.com/sally.xsl"?>
And the following content in sally.xsl:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="documentcollection/document">
<p>
<xsl:for-each select="rss/channel/item">
<xsl:value-of select="title"/><br />
<xsl:value-of select="description"/><br />
<xsl:value-of select="link"/><br />
</xsl:for-each>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
However, the browser displays the XML as though the XSL line is not present. Do you know why the browser is ignoring the XSL stylesheet? Is the style sheet wrong?
Thanks
I have the following XML:
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="http://www.fakedomain.com/sally.xsl"?>
This isn't a well-formed XML document (no top element present), so it isn't much of a surprize the browser doesn't treat it as such.
Solution:
Update your "XML" to a really well-formed XML document, something like:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="file:///c:/temp/delete/xxx.xsl"?>
<t/>
With this stylesheet in c:\temp\delete\xxx.xsl:
<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="/">
XXX
</xsl:template>
</xsl:stylesheet>
when the XML file is opened with IE, the browser displays the result of the transformation:
XXX
Looks like your not closing off one of your for-each tags?
the xsl:for-each loop of select="rss/channel/item" is not closed.
It could be same origin policy security restrictions. If your XML and XSLT are not hosted in the same location, then the browser may be refusing to fetch the XSLT and apply it to your XML file.

Categories