During xslt transformation, I have tried to clean string and special from customer number, but it doesnt work. I need to remove c: or s: from the number. Thanks :)
Xml File 1
<Data>
<Request>
<CustNo>c:222</CustNo>
</Request>
</Data>
Xml File 2
<Data>
<Request>
<CustNo>s:333</CustNo>
</Request>
</Data>
XSLT
<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" >
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="Request" >
<TestPayment>
<Transactions>
<Transaction custno="{CustNo}" >
</Transaction>
</Transactions>
</TestPayment>
</xsl:template>
<xsl:template match="Request/CustNo">
<xsl:value-of select="regex=(^c:[a-zA-Z0-9]*$,^s:[a-zA-Z0-9]*$ )"/>
</xsl:template>
</xsl:template>
</xsl:stylesheet>
Result of Xml File 1:
<?xml version="1.0" encoding="utf-8"?>
<TestPayment>
<Transactions>
<Transaction custno="222">
</Transaction>
</Transactions>
</TestPayment>
Result of Xml File 2:
<?xml version="1.0" encoding="utf-8"?>
<TestPayment>
<Transactions>
<Transaction custno="333">
</Transaction>
</Transactions>
</TestPayment>
In XSLT 2.0, you could do simply:
replace(CustNo, '\D', '')
to remove any non-digit characters.
Even in XSLT 1.0, you could use:
substring-after(CustNo, ':')
to accommodate both your examples.
why don't you try a double-translate function?
<Transaction custno="{translate(CustNo, translate(CustNo, '0123456789', ''), '')}" >
Related
for-each-group from XSLT 2.0 works as expected from a file but not from a variable.
Have this file:
~$ cat test.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<delimiter/>
<c>A</c><c>B</c>
<delimiter/>
<c>C</c>
</root>
Using stylesheet for grouping this file:
<?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" version="1.0"
encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
<xsl:template match="*">
<!-- variable not used for file test -->
<xsl:variable name="fields">
<root>
<delimiter/>
<c>A</c><c>B</c>
<delimiter/>
<c>C</c>
</root>
</xsl:variable>
<xsl:for-each-group select="*" group-starting-with="delimiter">
<field>
<xsl:for-each select="current-group()">
<xsl:value-of select="self::c"/>
</xsl:for-each>
</field>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
I get the result I want:
<?xml version="1.0" encoding="UTF-8"?>
<field>AB</field>
<field>C</field>
Trying to group the variable name="fields" with:
<xsl:for-each-group select="$fields/*" group-starting-with="delimiter">
I get the result:
<?xml version="1.0" encoding="UTF-8"?>
<field/>
Why does for-each-group works on a file but not from a variable?
The variable fields is a document-node(), you can define the type of the variable to be element()
<xsl:variable name="fields" as="element()">
<root>
<delimiter/>
<c>A</c><c>B</c>
<delimiter/>
<c>C</c>
</root>
</xsl:variable>
I need help preserving the namespace on XSLT transformation. I see other threads have solutions, but I don't understand them. When I use the XSLT transformation below, all the namespace disappears. Below is what I'm trying to accomplish. Any help is much appreciated! Thank you!
Before transform XML:
<?xml version='1.0' encoding='UTF-8'?>
<Worker
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:this="this.file/eib"
xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
xmlns:tv="java:com.workday.esb.intsys.TypedValue">
<Detail>
<EmployeeID>123456</EmployeeID>
<PayCode>Earning</PayCode>
<Amount>4243.20</Amount>
</Detail>
<Detail>
<EmployeeID>123456</EmployeeID>
<PayCode>Deduction</PayCode>
<Amount>2265.60</Amount>
</Detail>
</Worker>
My XSLT transformation:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" exclude-result-prefixes="xsl wd is xsd this env"
xmlns:wd="urn:com.workday/bsvc"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:this="urn:this-stylesheet">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/">
<xsl:copy>
<Worker>
<xsl:for-each select="Worker" >
<Detail>
<EmployeeID><xsl:value-of select="Detail[(PayCode ='Earning')]/EmployeeID"/></EmployeeID>
<PayCode><xsl:value-of select="Detail[(PayCode ='Earning')]/PayCode"/></PayCode>
<Amount><xsl:value-of select="Detail[(PayCode ='Earning') and (string-length(Amount) > 0)]/Amount"/></Amount>
</Detail>
</xsl:for-each>
</Worker>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Desired output:
<?xml version="1.0" encoding="UTF-8"?>
<Worker
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:this="this.file/eib"
xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
xmlns:tv="java:com.workday.esb.intsys.TypedValue">
<Detail>
<EmployeeID>123456</EmployeeID>
<PayCode>Earning</PayCode>
<Amount>4243.20</Amount>
</Detail>
</Worker>
At least in XSLT 2.0 (the version you used), namespaces disappear because you used exclude-result-prefixes attribute.
Just remove it and all namespaces included in your XSLT sheet, except for xsl, will be presented in the output, in the order of appearance.
But if you decided to omit all namespaces, it is easier to write exclude-result-prefixes="#all", instead of writing them again.
I can see no good reason to keep namespace declarations that are not used in your output. But if you really want to have them, why don't you simply copy them (as part of their parent element) - for example:
XSLT
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Worker">
<xsl:copy>
<xsl:copy-of select="Detail[PayCode ='Earning']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this is applied to your input example, the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<Worker xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:this="this.file/eib"
xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
xmlns:tv="java:com.workday.esb.intsys.TypedValue">
<Detail>
<EmployeeID>123456</EmployeeID>
<PayCode>Earning</PayCode>
<Amount>4243.20</Amount>
</Detail>
</Worker>
Demo: http://xsltransform.net/gVhD8Qt
I am writing xslt for filtering the data based on one of the fields.
Here is my input xml:
<?xml version="1.0" encoding="UTF-8"?>
<Consumer>
<header>
<msfnm>MSFNM</msfnm>
<mslnm>MSLNM</mslnm>
<msmnm>MSMNM</msmnm>
<msssn>MSSSN</msssn>
<csscstno>CSSCSTNO</csscstno>
<msact>MSACT</msact>
</header>
<data>
<msfnm>Nitin</msfnm>
<mslnm>Jain</mslnm>
<msmnm/>
<msssn>123</msssn>
<csscstno>111</csscstno>
<msact>1234</msact>
</data>
<data>
<msfnm>Nitin1</msfnm>
<mslnm>Jain1</mslnm>
<msmnm>L1</msmnm>
<msssn>1233</msssn>
<csscstno>111</csscstno>
<msact>1233556</msact>
</data>
<data>
<msfnm>Nitin2</msfnm>
<mslnm>Jain2</mslnm>
<msmnm>L1</msmnm>
<msssn>1234</msssn>
<csscstno>123</csscstno>
<msact>12334256</msact>
</data>
<data>
<msfnm>Nitin</msfnm>
<mslnm>Jain</mslnm>
<msmnm/>
<msssn>123</msssn>
<csscstno>111</csscstno>
<msact>1234</msact>
</data>
and I want my output xml should be like
<?xml version="1.0" encoding="UTF-8"?>
<Consumer>
<data>
<msfnm>Nitin</msfnm>
<mslnm>Jain</mslnm>
<msmnm/>
<msssn>123</msssn>
<csscstno>111</csscstno>
<msact>1234</msact>
</data>
<data>
<msfnm>Nitin2</msfnm>
<mslnm>Jain2</mslnm>
<msmnm>L1</msmnm>
<msssn>1234</msssn>
<csscstno>123</csscstno>
<msact>12334256</msact>
</data>
</Consumer>
Condition: basically what I want, to take first occurrence of csscstno only. If in next occurrence, csscstno is same, then the whole set should be rejected.
My xslt:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xml>
<xsl:for-each select="/Consumer/data">
<Consumer>
<msfnm><xsl:value-of select="msfnm"/></msfnm>
<mslnm><xsl:value-of select="mslnm"/></mslnm>
<msmnm><xsl:value-of select="msmnm"/></msmnm>
<msssn><xsl:value-of select="msssn"/></msssn>
<xsl:if test="position()=1">
<csscstno><xsl:value-of select="csscstno"/></csscstno>
</xsl:if>
<msact><xsl:value-of select="msact"/></msact>
</Consumer>
</xsl:for-each>
</xml>
</xsl:template>
</xsl:stylesheet>
This is not working. Let me know, what I am doing wrong here.
You can use keys. Just like the stylesheet below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" />
<!-- create a key for your target node -->
<xsl:key name="Customer_No" match="csscstno" use="."/>
<!-- copy only the 1st matched keys in the output -->
<xsl:template match="/">
<Consumer>
<xsl:copy-of select="Consumer/data[count(csscstno | key('Customer_No', csscstno)[1]) = 1]"/>
<!-- or you can use the following line instead
<xsl:copy-of select="Consumer/data[generate-id(csscstno) = generate-id(key('Customer_No', csscstno)[1])]"/>
-->
</Consumer>
</xsl:template>
</xsl:transform>
when this is applied to your input XML, the result is:
<?xml version="1.0" encoding="utf-8"?>
<Consumer>
<data>
<msfnm>Nitin</msfnm>
<mslnm>Jain</mslnm>
<msmnm/>
<msssn>123</msssn>
<csscstno>111</csscstno>
<msact>1234</msact>
</data>
<data>
<msfnm>Nitin2</msfnm>
<mslnm>Jain2</mslnm>
<msmnm>L1</msmnm>
<msssn>1234</msssn>
<csscstno>123</csscstno>
<msact>12334256</msact>
</data>
</Consumer>
Or, you can use keys for grouping data by csscstno to get the first occurence. Also, You can use a copy-of to select "data":
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="dataByCsscstno" match = "data" use = "csscstno"/>
<xsl:template match="/">
<Consumer>
<xsl:copy-of select="/Consumer/data[generate-id() = generate-id(key('dataByCsscstno', csscstno)[1])]"/>
</Consumer>
</xsl:template>
</xsl:stylesheet>
Eventually I have found another way, which is working as expected.
Here is my xslt:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xml>
<xsl:for-each-group select="/Consumer/data" group-by="csscstno">
<xsl:copy-of select="current-group()[1]"/>
</xsl:for-each-group>
</xml>
</xsl:template>
</xsl:stylesheet>
My real code is not this, but the problem that i am stating here applies to my real code.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book.child.1>
<title>charithram</title>
<author>sarika</author>
</book.child.1>
<book.child.2>
<title>doublebell</title>
<author>psudarsanan</author>
</book.child.2>
</books>
XSLT 1:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="/">
<xsl:for-each select="books/*">
<newbook>
<title>
<xsl:value-of select="title" />
</title>
</newbook>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
There in no output generated for this XSLT. I am trying using online tool: http://www.freeformatter.com/xsl-transformer.html
I could not understand what was wrong, Finally when I modified the XSLT like as written below,
XSLT 2:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="/">
<mytag>
<xsl:for-each select="books/*">
<newbook>
<title>
<xsl:value-of select="title" />
</title>
</newbook>
</xsl:for-each>
</mytag>
</xsl:template>
</xsl:stylesheet>
The output is generated in this case:
outputXML:
<?xml version="1.0" encoding="UTF-8"?>
<mytag>
<newbook>
<title>charithram</title>
</newbook>
<newbook>
<title>doublebell</title>
</newbook>
</mytag>
Can you please explain why is this behavior?
Also I don't know how exactly to ask this question, so please edit or let me know if i need to change the question title.
Your first XSLT will theoretically produce the output
<?xml version="1.0" encoding="UTF-8"?>
<newbook>
<title>charithram</title>
</newbook>
<newbook>
<title>doublebell</title>
</newbook>
But that output is not valid XML, because it has 2 root tags, which is not well-formed XML.
In this situation, you have probably the following choices
specify a root element like you did in XSLT 2
change the output from XML to TEXT, but be aware that any XML program will not be able to read the output
I want to transform an xml to naother xml, with xstl
I have an entity <AAA id="e1" ts=" bb">
How can i get this entity with the attributes in my new xml file?
The <xsl:copy-of> element can be used to accomplish what you're getting after.
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy-of select="AAA" />
</xsl:template>
</xsl:stylesheet>
...is run against the following sample XML:
<t>
<AAA id="e1" ts=" bb" />
</t>
...the wanted result is produced:
<?xml version="1.0" encoding="UTF-8"?>
<AAA id="e1" ts=" bb" />