Break statement in XSLT - xslt

I'm looking for kind of a break statement in XSLT.
Below is my input:
<ListOfCrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Pending</CRNEstimateAssignStatus>
</CrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Adjuster</CRNEstimatePackage>
<CRNEstimateAssignStatus>Pending1</CRNEstimateAssignStatus>
</CrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Inside Adjuster</CRNEstimatePackage>
<CRNEstimateAssignStatus>Moved to Mobile Claims</CRNEstimateAssignStatus>
</CrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Completed</CRNEstimateAssignStatus> <CRNEstimateAssignStatus>Completed</CRNEstimateAssignStatus>
</CrnEstimates>
</ListOfCrnEstimates>
Note: CRNEstimateAssignStatus values may differ...
I have to check for CRNEstimatePackage = Mobile Claims and have to create a request to backend with retaining that particular <CrnEstimates> and remove other <CrnEstimates>.
For the above request, I should generate 2 backend requests as below:
Output1:
<ListOfCrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Pending</CRNEstimateAssignStatus>
</CrnEstimates>
</ListOfCrnEstimates>
Output2:
<ListOfCrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Completed</CRNEstimateAssignStatus>
</CrnEstimates>
</ListOfCrnEstimates>
Currently I'm using below xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*:CrnEstimates[descendant::*:CRNEstimatePackage[. != 'Mobile Claims']]"/>
</xsl:stylesheet>
and Im getting below response:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfCrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Pending</CRNEstimateAssignStatus>
</CrnEstimates>
<CrnEstimates>
<CRNEstimatePackage>Mobile Claims</CRNEstimatePackage>
<CRNEstimateAssignStatus>Completed</CRNEstimateAssignStatus>
</CrnEstimates>
</ListOfCrnEstimates>

As i think you want to do nothing when CRNEstimatePackage[. != 'Mobile Claims'] that what it is dropping all CrnEstimates that descendant//CRNEstimatePackage values are not 'Mobile Claims'.

Related

adding segment to xml within the same xpath using xslt

I need to group some of the fields into a segment when the segment does not appear.
I am able to add the segment by checking if the segment already exists.
XML
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</ns1:MT_SalesOrder>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<ns0:stylesheet version="1.0" xmlns:ns0="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="urn:salesorder">
<ns0:output omit-xml-declaration="yes" indent="yes"/>
<ns0:strip-space elements="*"/>
<ns0:template match="node()|#*">
<ns0:copy>
<ns0:apply-templates select="node()|#*"/>
</ns0:copy>
</ns0:template>
<ns0:template match="/ns1:MT_SalesOrder[not(data)]">
<ns0:copy>
<ns0:apply-templates select="#*"/>
<data>
<ns0:apply-templates select="node()"/>
</data>
</ns0:copy>
</ns0:template>
</ns0:stylesheet>
I am expecting the below structure, data to be added before messageKey Field.
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<data> <---------------------------------------------
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
</data> <-------------------------------------------------
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</ns1:MT_SalesOrder>
But I am getting the data segment added to the whole XML.
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<data>
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</data>
</ns1:MT_SalesOrder>
I am not able to copy the part of the XML and group them, the field messageKey is the identifier to split the XML and add in data segment. Any leads will be helpful. Thank you!
If you know in advance the names of all elements in the two groups, then the best way is to list them explicitly:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:salesorder">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ns1:MT_SalesOrder">
<xsl:copy>
<data>
<xsl:copy-of select="Reason | OrderId | Invoice | Info | Comments | Status | Taxes | Due | OrderTotal"/>
</data>
<xsl:copy-of select="messageKey | message | errors | exceptions"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Otherwise you can use messageKey as the "split point":
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:salesorder">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ns1:MT_SalesOrder">
<xsl:copy>
<data>
<xsl:copy-of select="messageKey/preceding-sibling::*"/>
</data>
<xsl:copy-of select="messageKey | messageKey/following-sibling::*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

XSLT – Compare node values and pass attributes if nodes are equal

I am trying to do something that is probably very simple, but my very rudimentary xslt is not up to it.
Given the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<MyLists>
<List1>
<Place01 ctr="PTG">Lisbon</Place01>
<Place02 ctr="SPA">Madrid</Place02>
<Place03 ctr="FRA">Paris</Place03>
<Place04 ctr="ENG">York</Place04>
</List1>
<List2>
<Item01 type="country">Italy</Item01>
<Item02 type="person">John</Item02>
<Item03 type="city">York</Item03>
<Item04 type="city" subtype="capital">Madrid</Item04>
</List2>
</MyLists>
I would like to compare the text nodes from <List1> and <List2>, and, whenever their values are the same, pass, for each element, the attributes from <List2> to the corresponding items in <List1>, in order to get:
<?xml version="1.0" encoding="UTF-8"?>
<MyLists>
<List1>
<Place01 ctr="PTG">Lisbon</Place01>
<Place02 ctr="SPA" type="city" subtype="capital">Madrid</Place02>
<Place03 ctr="FRA">Paris</Place03>
<Place04 ctr="ENG" type="city">York</Place04>
</List1>
<List2>
<Item01 type="country">Italy</Item01>
<Item02 type="person">John</Item02>
<Item03 type="city">York</Item03>
<Item04 type="city" subtype="capital">Madrid</Item04>
</List2>
</MyLists>
Ideally, I'd like to be able to copy whichever attributes these element possess, without having to specify them.
Many thanks in advance!
If I understand this correctly, you could do something like:
XSLT 1.0
<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:strip-space elements="*"/>
<xsl:key name="match" match="Item" use="." />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Place">
<xsl:copy>
<xsl:copy-of select="key('match', .)/#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Biztalk Map node validation

I'm mapping home, work and mobile number nodes from the source schema to the home, work and mobile node in the destination schema.
I need to ensure that the data matches destination pattern (No space, punctuation, leading zeros, matching [+0][0-9]*. Can this be achieved via XSLT?
Source
<HTelephone>01656 123 123</HTelephone>
<WTelephone>01656-123-123</WTelephone>
<MTelephone>+447656 123 123</MTelephone>
Destination
<HTelephone>01656123123</HTelephone>
<WTelephone>01656123123</WTelephone>
<MTelephone>+447656123123</MTelephone>
Current Inline XSLT Call Template
<xsl:template name="MNo" xmlns:msxsl="urn:schemas-microsoft-com:xslt" >
<xsl:param name="inTelNo"/>
<xsl:element name="MTelephone" >
<xsl:value-of select="concat('+', translate($inTelNo, translate($inTelNo,'0123456789',''), ''))"/>
</xsl:element>
We need to validation the first character to allow a 0 or + also, any ideas?
Assuming correct input ( a root element to make it well-formed XML) use the concat() and translate functions to change the strings.
Input
<?xml version="1.0" encoding="utf-8"?>
<root>
<HTelephone>01656 123 123</HTelephone>
<WTelephone>01656 123 123</WTelephone>
<MTelephone>01656 123 123</MTelephone>
</root>
Stylesheet
<?xml version="1.0" encoding="utf-8"?>
<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:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/*">
<xsl:copy>
<xsl:value-of select="concat('+',translate(.,' ',''))"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="utf-8"?>
<root>
<HTelephone>+01656123123</HTelephone>
<WTelephone>+01656123123</WTelephone>
<MTelephone>+01656123123</MTelephone>
</root>

XSLT: How to expand child element to have extra parent element

I am trying to transform XML into another XML file but unsuccessfully changing a flat element into an expanded element.
The output should be identical except DateOfBirth should be changed to:
<DateOfBirth>
<FullDate xmlns="cds_dt">1966-02-11</FullDate>
</DateOfBirth>
Here are the input files I am using:
Input
*****
<?xml version="1.0" encoding="utf-8"?>
<RootRec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="cds">
<MyRecord>
<Demographics>
<Names>
<LegalName namePurpose="L" xmlns="cds_dt">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>1966-02-11</DateOfBirth>
<Demographics>
<MyRecord>
</RootRec>
XSL file
********
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!--Identity Template. This will copy everything as-is.-->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!--expand "DateOfBirth" element to /DateOfBirth/FullDate element.-->
<xsl:template match="RootRec/MyRecord/Demographics/DateOfBirth">
<DateOfBirth>
<FullDate><xsl:value-of select="DateOfBirth"/></FullDate>
</DateOfBirth>
</xsl:template>
</xsl:stylesheet>
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="cds">
<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="x:DateOfBirth/text()">
<xsl:element name="FullDate" xmlns="cds_dt"><xsl:value-of select="."/></xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided (corrected to be made wellformed) XML document:
<RootRec
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="cds">
<MyRecord>
<Demographics>
<Names>
<LegalName namePurpose="L" xmlns="cds_dt">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>1966-02-11</DateOfBirth>
</Demographics>
</MyRecord>
</RootRec>
produces the wanted, correct result:
<RootRec xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyRecord>
<Demographics>
<Names>
<LegalName xmlns="cds_dt" namePurpose="L">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>
<FullDate xmlns="cds_dt">1966-02-11</FullDate>
</DateOfBirth>
</Demographics>
</MyRecord>
</RootRec>
Explanation: Overriding the identity rule.
It should be
<FullDate><xsl:value-of select="."/></FullDate>
since you're already selecting the DateOfBirth in the match=""
You also have missing / in the three closing tags before the document end, and your namespace names are invalid because they must be absolute URIs.
Good luck.

How to replace element with XSLT by keeping the namespace prefix

I am looking for a way to replace the value of a field from a xml file by using xslt. Everything works great besides the namespace prefix. In the source file below I want to change the Password element value.
<?xml version="1.0" encoding="utf-8"?>
<ns0:MYXML xmlns:ns0="http://www.me.com/myxml" xmlns="http://www.me.com/myxml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Header>
<ns0:Infromation>
<ns0:From>
<ns0:Credential>
<ns0:User>jeff</ns0:User>
<Password xmlns="">OLD VALUE</Password>
</ns0:Credential>
</ns0:From>
</ns0:Infromation>
<ns0:Misc>
<ns0:ID>1002</ns0:ID>
<ns0:Timestamp>2012-01-16T09:23:33</ns0:Timestamp>
<ns0:Type>unknown</ns0:Type>
</ns0:Misc>
<ns0:State>
<ns0:ConversationId>d66d9304-9025-a580-e111-5640bf36560d</ns0:ConversationId>
</ns0:State>
</ns0:Header>
</ns0:MYXML>
Here is my result:
<?xml version="1.0" encoding="utf-8"?>
<ns0:MYXML xmlns:ns0="http://www.me.com/myxml" xmlns="http://www.me.com/myxml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Header>
<ns0:Infromation>
<ns0:From>
<ns0:Credential>
<ns0:User>jeff</ns0:User>
<Password xmlns="">New Value</Password>
</ns0:Credential>
</ns0:From>
</ns0:Infromation>
<ns0:Misc>
<ns0:ID>1002</ns0:ID>
<ns0:Timestamp>2012-01-16T09:23:33</ns0:Timestamp>
<ns0:Type>unknown</ns0:Type>
</ns0:Misc>
<ns0:State>
<ns0:ConversationId>d66d9304-9025-a580-e111-5640bf36560d</ns0:ConversationId>
</ns0:State>
</ns0:Header>
</ns0:MYXML>
And that's the xslt code that I use for the transformation:
<?xml version="1.0" encoding="utf-8"?>
<ns0:MYXML xmlns:ns0="http://www.me.com/myxml" xmlns="http://www.me.com/myxml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Header>
<ns0:Infromation>
<ns0:From>
<ns0:Credential>
<ns0:User>jeff</ns0:User>
<Password xmlns="">New Value</Password>
</ns0:Credential>
</ns0:From>
</ns0:Infromation>
<ns0:Misc>
<ns0:ID>1002</ns0:ID>
<ns0:Timestamp>2012-01-16T09:23:33</ns0:Timestamp>
<ns0:Type>unknown</ns0:Type>
</ns0:Misc>
<ns0:State>
<ns0:ConversationId>d66d9304-9025-a580-e111-5640bf36560d</ns0:ConversationId>
</ns0:State>
</ns0:Header>
</ns0:MYXML>
i tried to use "{name()}" for the element name but this throws an exception that the namespace does not exist.
Any help is greatly appreciated!
It's not clear to me whether you want the Password element to belong to the empty namespace as it appears in the original Xml or you want it to be in the http://www.me.com/myxml namespace. Here is an Xslt stylesheet that replaces the Password element from the empty namespace with a Password element from the http://www.me.com/myxml namespace (I used ns0 prefix so that it looks like other elements in the Xml document):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Password">
<ns0:Password xmlns:ns0="http://www.me.com/myxml">
<xsl:copy-of select="#*"/>
<xsl:text>New Value</xsl:text>
</ns0:Password>
</xsl:template>
<!-- This creates the element in the empty namespace
<xsl:template match="Password">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:text>New Value</xsl:text>
</xsl:copy>
</xsl:template>
-->
</xsl:stylesheet>
I also included a template that copies the existing Password element and replaces its value just in case you need it. If you don't need it you can remove the block entirely.
Here is the transformation result:
<?xml version="1.0" encoding="utf-8"?>
<ns0:MYXML xmlns:ns0="http://www.me.com/myxml" xmlns="http://www.me.com/myxml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Header>
<ns0:Infromation>
<ns0:From>
<ns0:Credential>
<ns0:User>jeff</ns0:User>
<ns0:Password>New Value</ns0:Password>
</ns0:Credential>
</ns0:From>
</ns0:Infromation>
<ns0:Misc>
<ns0:ID>1002</ns0:ID>
<ns0:Timestamp>2012-01-16T09:23:33</ns0:Timestamp>
<ns0:Type>unknown</ns0:Type>
</ns0:Misc>
<ns0:State>
<ns0:ConversationId>d66d9304-9025-a580-e111-5640bf36560d</ns0:ConversationId>
</ns0:State>
</ns0:Header>
</ns0:MYXML>
Pawel