from string to number xslt - string

I want to make a comparison of two different date’s. To realize that, I want to transform to number.
Input example:
<file>
<date>2015-11-06 09:00/>
</file>
<history>
<date>2016-01-12 10:00/>
</history>
First I extract the time, from date. And put the result in a var.
<xsl:for-each select="//item/metadata/document/file/date">
<xsl:variable name="d_log"
select="substring-before(., ' ')" as="xs:string"/>
So the value of the variable would be, for example 2015-11-06.
The next step is, that I want to transform 2015-11-06 in to 20151106.
Questions is how I can transform from a string to a number?
Or is there a easier way?

You can do:
translate(substring-before(., ' '), '-', '')
to get the expected number.
However, your syntax suggests you are using XSLT 2.0. If so, why don't you convert the given strings to xs:date or xs:dateTime and compare them as such?

Here is my result.
<?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"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" indent="yes"></xsl:output>
<xsl:template match="/">
<aaa>
<xsl:for-each select="//item/metadata/document/file/date">
<xsl:variable name="d_log"
select="translate(substring-before(., ' '), '-', '')"
as="xs:string"/>
<xsl:for-each select="../../history/log/date">
<xsl:variable name="d_doc" select="translate(substring-before(., ' '), '-', '')" as="xs:string"/>
<xsl:if test="$d_doc > $d_log">
<bb>
<xsl:value-of select="node()"/>
</bb>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</aaa>
</xsl:template>
</xsl:stylesheet>

Related

How to return the count of input that start with a string in XSL?

I'm trying to return the count of names which start with NB but im having trouble as it returns 0. I believe i got the syntax right so it's kind of frustrating to see it return 0. Any help would be appreciated!
XML Input:
<?xml version='1.1' encoding='UTF-8'?>
<breaches>
<breach>
<name>NB111</name>
<severity>MAJOR</severity>
</breach>
<breach>
<name>NB222</name>
<severity>MAJOR</severity>
</breach>
<breach>
<name>NB333</name>
<severity>MAJOR</severity>
</breach>
<breach>
<name>PO999</name>
<severity>MAJOR</severity>
</breach>
</breaches>
XSL
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="count(/breaches/breach/name/*[contains(text(), 'NB')])" />
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>0
I'm trying to return the count of names which start with NB
If you want to count names that start with "NB" then use the starts-with() function, not the contains() function:
<xsl:value-of select="count(breaches/breach[starts-with(name, 'NB')])"/>
This actually counts breach elements that have a child name element that starts with "NB". IOW, it assumes each breach has only one name. If such assumption is incorrect, then use:
<xsl:value-of select="count(breaches/breach/name[starts-with(., 'NB')])"/>
to count the actual name elements.
You could do it like this :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="count(breaches/breach/name[contains(., 'NB')])" />
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/jxWZS86

XSL loop through faultblock and apppend values to a string without using template

How to loop through fault_block and append values to a string/variable without using template in XSLT. fault_block may occur once or twice or n number of times based on validation errors
Desired Output: 11-Invalid ID;22-Invalid Password;.....nn-Error;
<status>
<code>00</code>
<description>Success</description>
<faultblock>
<faultcode>11</faultcode>
<faultdesc>Invalid ID</faultdesc>
</faultblock>
<faultblock>
<faultcode>22</faultcode>
<faultdesc>Invalid Password</faultdesc>
</faultblock>
<faultblock>
<faultcode>nn</faultcode>
<faultdesc>Error</faultdesc>
</faultblock>
</status>
I'm guessing you want to get your output using only a for-each statement instead of using multiple templates.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:for-each select="//faultblock">
<xsl:value-of select="faultcode"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="faultdesc"/>
<xsl:text>;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
See it working here: https://xsltfiddle.liberty-development.net/6pS2B71

Add '(apostrophe) as a valid character in XSLT template

I am working on a project there they have given a list of valid characters which should be passed as it is and any other characters other than them has to be replaced with ?(question mark).
My company software does not allows to use replace function, so i have to use translate method.
I am able to add all the valid characters except '(apostrophe). How to include apostrophe also as a valid character in variable vAllowedSymbols.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="vAllowedSymbols" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890/-?:(),.+ '"/>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="
translate(
.,
translate(., $vAllowedSymbols, ''),
''
)
"/>
</xsl:template>
Input:
<t>
<Name>#O'Niel</Name>
<Name>St: Peter</Name>
<Name>A.David</Name>
</t>
Output:
<t>
<Name>?O'Niel</Name>
<Name>St: Peter</Name>
<Name>A.David</Name>
</t>
Use
<xsl:variable name="vAllowedSymbols">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890/-?:(),.+ '</xsl:variable>
<xsl:variable name="vAllowedSymbols" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890/-?:(),.+ &apos;"'/>
There is some advantage in having the variable contain a string instead of a text node. Or more precisely, be a string instead of a node-set that contains a text node.

Populating nodes based on condition in Receiver file

I need to populate one segment based on input values.the requirement like below
in the input payload we are getting below segment like
<charac>
<charactername>
<charactervalue>
</charac>
so the above segment may come multiple times but based on the few values only need to populate the segment for example,
<charac>
<charactername>print</charactername>
<charactervalue>123</charactervalue>
</charac>
<charac>
<charactername>comp</charactername>
<charactervalue>1234</charactervalue>
</charac>
<charac>
<charactername>pal</charactername>
<charactervalue>1235</charactervalue>
</charac>
so here only I need populate segment when charactername is equal to only print or comp
the receiver structure the segment is
<e1edl1>
<at>
<rt>
</e1edl1>
so the output should be like
<e1edl1>
<at>print</at>
<rt>123</rt>
</e1edl1>
<e1edl1>
<at>comp</at>
<rt>1234</rt>
</e1edl1>
I tried with below code
<ns0:if test="count(./charac)!=0">
<ns0:for-each select="./charac">
<e1edl1 SEGMENT="1">
<at>
<ns0:value-of select="charactername" />
</at>
<rt>
<ns0:value-of select="charactervalue" />
</rt>
</e1edl1>
</ns0:for-each>
</ns0:if>
could you please help on this.
Regards,
Janardhan
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//charac[charactername='print' or charactername='comp']" />
</xsl:template>
<xsl:template match="charac">
<e1edl1>
<at><xsl:value-of select="charactername" /></at>
<rt><xsl:value-of select="charactervalue" /></rt>
</e1edl1>
</xsl:template>
</xsl:stylesheet>

XSLT finding matching node by comparing element text to substring result

I am processing this XML:
<Brand>
<Brand_Name>BLENDERM</Brand_Name>
<Brand_Code>1103</Brand_Code>
<Groups>
<Group>
<Group_Code>657</Group_Code>
<Parent_Code>0</Parent_Code>
<Group_Level>1</Group_Level>
<Group_Name>Brand Default</Group_Name>
<Product>
<Pip_code>0032359</Pip_code>
<Status>In Use</Status>
Using this XSLT:
<xsl:template match="Product" mode="phase-3">
<xsl:value-of select="document('rx_catmapping.xml')/descendant::mapping[source=substring(ancestor::Brand/Brand_Name,1,1)]/target"/>
</xsl:template>
Here is a sample of rx_catmapping.xml:
<Lookup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<mapping>
<source>a</source>
<target>788</target>
</mapping>
<mapping>
<source>B</source>
<target>789</target>
</mapping>
</Lookup>
So, I am processing the Product element, which is a descendant of Brand. The first letter of Brand/Brand_Name in this case is B, and I am trying to output the value 789 by looking it up in rx_catmapping.xml. This should be really simple but I am completely stumped! I have tried changing the first part of the XPath to refer to document('rx_catmapping.xml')/Lookup/mapping, or document('rx_catmapping.xml')//mapping. I have also tried changing the first half of the comparison to string(source), or to source/text(), but neither of these works either. (The reason for trying this was that using source='B', for example, did seem to work, so I wondered if I was trying to compare two incompatible data types.)
Thanks in advance for your help.
Define a key
<xsl:key name="k1" match="mapping" use="source"/>
then use
<xsl:variable name="map-doc" select="document('rx_catmapping.xml')"/>
and
<xsl:variable name="letter" select="substring(ancestor::Brand/Brand_Name,1,1)"/>
<xsl:for-each select="$map-doc">
<xsl:value-of select="key('k1', $letter)/target"/>
</xsl:for-each>
With XSLT 2.0 you can simplify that to
<xsl:value-of select="key('k1', substring(ancestor::Brand/Brand_Name,1,1), $map-doc)"/>
The problem is, I believe, that at the point where you do ancestor::Brand/Brand_Name, the context is the mapping element in the external file. This worked for me
<xsl:template match="/">
<xsl:apply-templates select=".//Product"/>
</xsl:template>
<xsl:template match="Product">
<xsl:variable name="x" select="substring(ancestor::Brand/Brand_Name,1,1)"/>
<xsl:value-of select="document('file:///c:/temp/rx_catmapping.xml')//mapping[source=$x]/target"/>
</xsl:template>

Resources