How get String before hyphen in XSLT - xslt

I want yo get the first name initial and last name.
Input :
<root>
<ele str="Great Success-Turbo Pat(by Sundon) [Cheeky Pat 8m(Monarchy)"/>
<ele str="Brylin Boyz-Scallywag"/>
<ele str="Majestic Son-Be Bee"/>
</root>
Output
<names>Great Success</name>
<names>Brylin Boyz</name>
<names>Majestic Son</name>
Tried Code:
<xsl:template match="root/name">
<names>
<xsl:value-of select="#str" />
</name>
</xsl:template>
I am using XSLT 2.0. Thank you

You need to use fn:substring-before() :
<xsl:template match="ele">
<name>
<xsl:value-of select="substring-before(#str, '-')" />
</name>
</xsl:template>

Related

How get first name initial and last name in XSLT

I want yo get the first name initial and last name.
Input :
<root>
<ele name="Samp Huwani"/>
<ele name="Gong Gitry"/>
<ele name="Dery Wertnu"/>
</root>
Output
<names>S Huwani</name>
<names>G Gitry</name>
<names>D Wertnu</name>
Tried Code:
<xsl:template match="root/name">
<names>
<xsl:value-of select="#name" />
</name>
</xsl:template>
I am using XSLT 2.0 . Thank you
With the given example, you could use:
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="ele">
<name>
<xsl:value-of select="substring(#name, 1, 1)"/>
<xsl:text> </xsl:text>
<xsl:value-of select="substring-after(#name, ' ')"/>
</name>
</xsl:for-each>
</xsl:copy>
</xsl:template>
However, names often do not conform to the same pattern.
In XSLT 2.0, you could simplify(?) this by using regex, e.g.:
<xsl:value-of select="replace(#name, '^(.{1}).* (.*)', '$1 $2')"/>

Get parent node from child and rename it

I have the input bellow and I wrote some xslt that gives me an office with a specific ID but since I get the parent node I also get the tag <e>. My problem is that I don't want to have that <e> tag.
<response>
<offices>
<e>
<id>33701</id>
<name>aa</name>
</e>
.....<e></e>
</offices>
</response>
<xsl:template match="*:response/offices">
<econ:GetOfficesResponse>
<Office>
<xsl:for-each select="e/id">
<xsl:if test="text() = $office_id">
<xsl:copy-of select="parent::node()"/>
</xsl:if>
</xsl:for-each>
</Office>
</econ:GetOfficesResponse>
</xsl:template>
</xsl:stylesheet>
The response that I get:
<econ:GetOfficesResponse>
<Office>
<e>
<id>33701</id>
<name>...</name>
</e>
</Office>
The response that I want:
<econ:GetOfficesResponse>
<Office>
<id>33701</id>
<name>...</name>
</Office>
Can someone please help me with this? I/m using xslt 2.0
It seems like instead of your xsl:for-each you simply want a single <xsl:copy-of select="e[id = $office_id]/*"/>
try this code:
<xsl:template match="*:response/offices">
<econ:GetOfficesResponse>
<Office>
<xsl:for-each select="e/id">
<xsl:if test="text() = $office_id">
<xsl:copy-of select="parent::node()/child::node()"/>
</xsl:if>
</xsl:for-each>
</Office>
</econ:GetOfficesResponse>
</xsl:template>

XML to pipe-delimited - How to copy/duplicate data to different rows

I'm new to XSLT and trying to transform from XML to pipe-delimited format. The problem that I'm having is that in the output, each claim has to be duplicated for each service line.
Expected Output:
EP030315706890704|TESTSUBMITTER|FAMILY HEALTHCARE|1122334455|1|99214|179.00
EP030315706890704|TESTSUBMITTER|FAMILY HEALTHCARE|1122334455|2|2000F|0.00
EP030315706890705|TESTSUBMITTER2|FAMILY HEALTHCARE|1122334455|1|99214|179.00
EP030315706890705|TESTSUBMITTER2|FAMILY HEALTHCARE|1122334455|2|2000F|0.00
Input XML looks as follows:
<payloadContainer>
<afile>
<clm>
<hdr>
<corn>EP030315706890704</corn>
<idSend>112233445</idSend>
<nmSend>TESTSUBMITTER</nmSend>
</hdr>
<provBill>
<name>
<nmOrg>FAMILY HEALTHCARE</nmOrg>
</name>
<id T="XX" P="P">1122334455</id>
</provBill>
<serv S="1">
<numLine>1</numLine>
<prof>
<px L="S">
<cdPx T="HC">99214</cdPx>
</px>
<amtChrg>179.00</amtChrg>
</prof>
</serv>
<serv S="2">
<numLine>2</numLine>
<prof>
<px L="S">
<cdPx T="HC">2000F</cdPx>
</px>
<amtChrg>0.00</amtChrg>
</prof>
</serv>
</clm>
<clm>
<hdr>
<corn>EP030315706890705</corn>
<idSend>112233445</idSend>
<nmSend>TESTSUBMITTER2</nmSend>
</hdr>
<provBill>
<name>
<nmOrg>FAMILY HEALTHCARE</nmOrg>
</name>
<id T="XX" P="P">1122334455</id>
</provBill>
<serv S="1">
<numLine>1</numLine>
<prof>
<px L="S">
<cdPx T="HC">99214</cdPx>
</px>
<amtChrg>179.00</amtChrg>
</prof>
</serv>
<serv S="2">
<numLine>2</numLine>
<prof>
<px L="S">
<cdPx T="HC">2000F</cdPx>
</px>
<amtChrg>0.00</amtChrg>
</prof>
</serv>
</clm>
</afile>
</payloadContainer>
Desired output XML:
<Table>
<row>
.... All the fields represented here.
</row>
</Table>
Possible solution: https://www.dropbox.com/s/wzvtzw7ihtgxx9o/claimtoRedshift.xsl
This scenario creates two row's dynamically. However, I'm still stuck at how to duplicate for each service line.
I don't see the connection of the linked XSLT to the question presented here. AFAICT, the following stylesheet will return the expected pipe-delimited output:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/payloadContainer">
<xsl:for-each select="afile/clm">
<xsl:variable name="common">
<xsl:value-of select="hdr/corn"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="hdr/nmSend"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="provBill/name/nmOrg"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="provBill/id"/>
<xsl:text>|</xsl:text>
</xsl:variable>
<xsl:for-each select="serv">
<xsl:value-of select="$common"/>
<xsl:value-of select="numLine"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="prof/px/cdPx"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="prof/amtChrg"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

in xslt how to compare a string value with another variable containing multiple values

I have the following xml file. I need to fetch all unique "owner" values from this and perform some operations.
<issues>
<issue>
<owner>12345</owner>
</issue>
<issue>
<owner>87654</owner>
</issue>
<issue>
<owner>12345</owner>
</issue>
</issues>
<tests>
<test>
<owner>34598</owner>
</test>
<test>
<owner>12345</owner>
</test>
<test>
<owner>34598</owner>
</test>
<test>
<owner>11111</owner>
</test>
</tests>
I tried using following xslt script.
<xsl:for-each select="issues/issue[not(child::owner=preceding- sibling::issue/owner)]/owner">
<!--some code-->
</xsl:for-each>
<xsl:for-each select="tests/test[not(child::owner=preceding- sibling::test/owner)]/owner">
<xsl:variable name="IrmAs">
<xsl:value-of select="." />
</xsl:variable>
<xsl:variable name="IssueList">
<xsl:value-of select="//issues/issue/owner">
</xsl:variable>
<xsl:if test="not(contains($IssueList,$IrmAs))">
<!--some code-->
</xsl:if>
</xsl:for-each>
But am getting duplicate values. Could anyone please help me with this?
In XSLT 2.0 you can just use for-each-group:
<xsl:for-each-group select="issues/issue | tests/test" group-by="owner">
<!-- in here, . is the first issue/test with a given owner and current-group()
is the sequence of all issue/test elements that share the same owner -->
</xsl:for-each-group>
If you are stuck on 1.0 then you need to use a technique called "Muenchian grouping" - define a key that groups elements with the same owner, then process just the first item in each group using a generate-id trick
<xsl:key name="ownerKey" match="issue | test" use="owner" />
<xsl:for-each select="(issues/issue | tests/test)[generate-id()
= generate-id(key('ownerKey', owner)[1])]">
<!-- one iteration per unique owner, with . being the parent element of the
first occurrence -->
</xsl:for-each>
But am getting duplicate values.
It's not quite clear where you are getting the duplicate values - since your posted code does not output anything. If you had tested something like:
...
<xsl:for-each select="issues/issue[not(child::owner=preceding-sibling::issue/owner)]/owner">
<out>
<xsl:value-of select="." />
</out>
</xsl:for-each>
....
you would have seen that it does work (albeit inefficiently) and returns:
...
<out>12345</out>
<out>87654</out>
...
Similarly, testing the following snippet:
...
<xsl:for-each select="tests/test[not(child::owner=preceding-sibling::test/owner)]/owner">
<xsl:variable name="IrmAs">
<xsl:value-of select="." />
</xsl:variable>
<xsl:variable name="IssueList">
<xsl:value-of select="//issues/issue/owner"/>
</xsl:variable>
<xsl:if test="not(contains($IssueList,$IrmAs))">
<out>
<xsl:value-of select="." />
</out>
</xsl:if>
</xsl:for-each>
...
produces:
...
<out>34598</out>
<out>11111</out>
...
So the problem must be in the part of the code that you haven't posted. Note also that the code you did post has several syntax errors, e.g. :
<xsl:value-of select="//issues/issue/owner">
needs to be:
<xsl:value-of select="//issues/issue/owner"/>

how to call my template and my function sequentially in xslt 2.0?

I am using xslt2.0 for convert one xml format to another xml format. This is my sample xml document.
<w:document>
<w:body>
<w:p>Para1</w:p>
<w:p>Para2</w:p>
<w:p>Para3</w:p>
<w:p>Para4</w:p>
</w:body>
</w:document>
Initially this is my xml format.so, i handled each and every <w:p> elements through my function in xslt given below...
<xsl:template match="document">
<Document>
<xsl:sequence select="mf:group(body/p, 1,count(//w:body//w:p)-1)"/>
</Document>
</xsl:template>
So,In that xslt function, i have coded how to reformat those elements.It's working fine...
But now,Xml format is restructured like given below...
<w:document>
<w:body>
<w:tbl><!--some text with children elements--></w:tbl>
<w:tbl><!--some text with children elements--></w:tbl>
<w:p>Para1</w:p>
<w:p>Para2</w:p>
<w:p>Para3</w:p>
<w:p>Para4</w:p>
</w:body>
</w:document>
So, As of now i have to handle both and elements in a same sequence.....
What i want to do is,
If i encounter elemtents then i have to call my template given below...
<xsl:template match="document">
<Document>
<xsl:for-each select="w:tbl">
<xsl:apply-templates select="w:tbl">
</xsl:apply-templates>
</xsl:for-each>
<xsl:sequence select="mf:group(body/p, 1,count(//w:body//w:p)-1)"/>
</Document>
</xsl:template>
<xsl:template match="w:tbl">
<!--xslt code here -->
</xsl:template>
But the for-each statement is not executed when I trying transformation...
So, Please guide me to get out of this issue...
I think instead of
<xsl:template match="document">
<Document>
<xsl:for-each select="w:tbl">
<xsl:apply-templates select="w:tbl">
</xsl:apply-templates>
</xsl:for-each>
<xsl:sequence select="mf:group(body/p, 1,count(//w:body//w:p)-1)"/>
</Document>
</xsl:template>
you simply want
<xsl:template match="document">
<Document>
<xsl:apply-templates select="w:body/w:tbl"/>
<xsl:sequence select="mf:group(body/p, 1,count(//w:body//w:p)-1)"/>
</Document>
</xsl:template>
If that does not do what you want then please show the result you want.