I am trying to multiple AND condition within If cause in XSLT and it is not working. Below is the code snippet I am trying to write.
Code Snippet :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:dpconfig="http://www.datapower.com/param/config" version="1.0" extension-element-prefixes="dp" exclude-result-prefixes="dp dpconfig">
<xsl:output method="xml" />
<xsl:variable name="vAccStatus" select="dp:http-request-header('AccStatus')" />
<xsl:variable name="vRules" select="dp:http-request-header('Rules')" />
<xsl:variable name="vAccess" select="dp:http-request-header('Access')" />
<xsl:variable name="vOut" select="dp:http-request-header('Out')" />
<xsl:variable name="vUserAccess" select="dp:http-request-header('UserAccess')" />
<xsl:variable name="vLevel" select="dp:http-request-header('Level')" />
<xsl:variable name="vPerformed" select="dp:http-request-header('Performed')" />
<xsl:variable name="vParticipation" select="dp:http-request-header('Participation')" />
<xsl:variable name="vPoints" select="dp:http-request-header('Points')" />
<xsl:template match="/">
<xsl:variable name="res">
<NS1:AuthResponse xmlns:NS1="http://test.com/test">
<NS1:AuthDetails>
<NS1:Detail>
<NS1:AuthCheckType>FunctionsPerformed</NS1:AuthCheckType>
<NS1:Result>NOT_PERFORMED</NS1:Result>
<NS1:ErrorCode />
<NS1:AuthDetails />
</NS1:Detail>
<NS1:Detail>
<NS1:AuthCheckType>ServiceParticipation</NS1:AuthCheckType>
<NS1:Result>NOT_PERFORMED</NS1:Result>
<NS1:ErrorCode />
<NS1:AuthDetails />
</NS1:Detail>
</NS1:AuthDetails>
<NS1:Access>GRANT_ACCESS</NS1:Access>
<NS1:ErrorCode>0</NS1:ErrorCode>
</NS1:AuthResponse>
</xsl:variable>
<xsl:if test="(($vAccStatus = 'N') and ($vRules = 'N') and ($vAccess = 'N') and ($vOut = 'N') and ($vUserAccess = 'N') and ($vLevel = 'N') and ($vPerformed = 'N') and ($vParticipation = 'N') and ($vPoints = 'N'))">
<xsl:copy-of select="$res"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Can you please let me know what is the issue here and how to make it work
it is not executing the statements within the IF clause even if the
conditions are satisfying.
I believe you are mistaken about this. If the instructions contained in your xsl:if statement are not executed, it is because the test returns false. You can verify this by running the following stylesheet and adding the result to your question:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
extension-element-prefixes="dp">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="vAccStatus" select="dp:http-request-header('AccStatus')" />
<xsl:variable name="vRules" select="dp:http-request-header('Rules')" />
<xsl:variable name="vAccess" select="dp:http-request-header('Access')" />
<xsl:variable name="vOut" select="dp:http-request-header('Out')" />
<xsl:variable name="vUserAccess" select="dp:http-request-header('UserAccess')" />
<xsl:variable name="vLevel" select="dp:http-request-header('Level')" />
<xsl:variable name="vPerformed" select="dp:http-request-header('Performed')" />
<xsl:variable name="vParticipation" select="dp:http-request-header('Participation')" />
<xsl:variable name="vPoints" select="dp:http-request-header('Points')" />
<xsl:template match="/">
<variables>
<vAccStatus>
<xsl:value-of select="$vAccStatus"/>
</vAccStatus>
<vRules>
<xsl:value-of select="$vRules"/>
</vRules>
<vAccess>
<xsl:value-of select="$vAccess"/>
</vAccess>
<vOut>
<xsl:value-of select="$vOut"/>
</vOut>
<vUserAccess>
<xsl:value-of select="$vUserAccess"/>
</vUserAccess>
<vLevel>
<xsl:value-of select="$vLevel"/>
</vLevel>
<vPerformed>
<xsl:value-of select="$vPerformed"/>
</vPerformed>
<vParticipation>
<xsl:value-of select="$vParticipation"/>
</vParticipation>
<vPoints>
<xsl:value-of select="$vPoints"/>
</vPoints>
</variables>
</xsl:template>
</xsl:stylesheet>
Related
XSLT:
Written my XSLT like this but I'm not getting required output as below that means I want to loop through each record and get frontimagefilename and rearimagefilename for each check.
<xsl:template name="ChequeDetailsTemplate">
<xsl:param name ="vItemcurrIndx" />
<xsl:variable name ="x" select ="$allRecs[$vItemcurrIndx]/Content/*" />
<xsl:call-template name="loop">
<xsl:with-param name="i" select="1"/>
<xsl:with-param name="limit" select="$x/NumberOfCheques"/>
<xsl:with-param name="vItemcurrIndx" select="position()"></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="loop">
<xsl:param name="i"/>
<xsl:param name="limit"/>
<xsl:param name ="vItemcurrIndx" />
<xsl:variable name ="y" select ="$allRecs[$vItemcurrIndx]/Content/*" />
<xsl:if test="$i <= $limit">
<Check>
<CheckAmount><xsl:value-of select="concat(./CourtesyAmount,$i)"/> </CheckAmount>
<FrontImage><xsl:value-of select="concat(./FrontImageFilename,$i)"/></FrontImage>
<RearImage><xsl:value-of select="concat(./RearImageFilename,$i)"/></RearImage>
</Check>
<xsl:call-template name="loop">
<xsl:with-param name="i" select="$i+1"/>
<xsl:with-param name="limit" select="$limit"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
Output looking for:
-<Check><CheckAmount>300</CheckAmount><Codeline><006474< :########## 12345678<</Codeline><FrontImage>C:\Jan292015\archive (1) - Copy\archive\BIN\TempChequeImages\CHQNCR-2VD8NP348TD20150129135318f001.tif</FrontImage><RearImage>C:\Jan292015\archive (1) - Copy\archive\BIN\TempChequeImages\CHQNCR-2VD8NP348TD20150129135318r001.tif</RearImage><CourtesyAmount>300</CourtesyAmount></Check>-<Check><CheckAmount>300</CheckAmount><Codeline><006474< :########## 12345678<</Codeline><FrontImage>C:\Jan292015\archive (1) - Copy\archive\BIN\TempChequeImages\CHQNCR-2VD8NP348TD20150129135320f002.tif</FrontImage><RearImage>C:\Jan292015\archive (1) - Copy\archive\BIN\TempChequeImages\CHQNCR-2VD8NP348TD20150129135320r002.tif</RearImage><CourtesyAmount>300</CourtesyAmount></Check>
But the output which im getting now is:
-<Check><CheckAmount>1</CheckAmount><FrontImage>1</FrontImage><RearImage>1</RearImage></Check>-<Check><CheckAmount>2</CheckAmount><FrontImage>2</FrontImage><RearImage>2</RearImage></Check>
If I am guessing (!) correctly, your input looks something like this:
<ChqDepAppSrvChequeScanComplete>
<CourtesyAmount1>100</CourtesyAmount1>
<FrontImageFilename1 t="String">R:\bin_simulated\Images\TempChequeImages\100f001.bmp</FrontImageFilename1>
<RearImageFilename1 t="String">R:\bin_simulated\Images\TempChequeImages\100r001.bmp</RearImageFilename1>
<RefuseReason1 t="String">None</RefuseReason1>
<CourtesyAmount2>200</CourtesyAmount2>
<FrontImageFilename2 t="String">R:\bin_simulated\Images\TempChequeImages\200f002.bmp</FrontImageFilename2>
<RearImageFilename2 t="String">R:\bin_simulated\Images\TempChequeImages\200r002.bmp</RearImageFilename2>
<RefuseReason2 t="String">None</RefuseReason2>
<NumberOfCheques t="Int32">2</NumberOfCheques>
</ChqDepAppSrvChequeScanComplete>
Your mistake is in the way you have built this expression:
<xsl:value-of select="concat(./CourtesyAmount,$i)"/>
There is no <CourtesyAmount> node in your input, so you are concatenating nothing and $i, resulting in the current value of $i.
What you really want to do here is get the value from a node whose name is the concatenation of the string "CourtesyAmount" and the current value of $i. 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:template match="/ChqDepAppSrvChequeScanComplete">
<output>
<xsl:call-template name="loop">
<xsl:with-param name="limit" select="NumberOfCheques"/>
</xsl:call-template>
</output>
</xsl:template>
<xsl:template name="loop">
<xsl:param name="i" select="1"/>
<xsl:param name="limit"/>
<xsl:if test="$i <= $limit">
<Check>
<CheckAmount>
<xsl:value-of select="*[local-name()=concat('CourtesyAmount', $i)]"/>
</CheckAmount>
<FrontImage>
<xsl:value-of select="*[local-name()=concat('FrontImageFilename', $i)]"/>
</FrontImage>
<RearImage>
<xsl:value-of select="*[local-name()=concat('RearImageFilename', $i)]"/>
</RearImage>
</Check>
<xsl:call-template name="loop">
<xsl:with-param name="i" select="$i+1"/>
<xsl:with-param name="limit" select="$limit"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
which when applied to the above input will result in:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<Check>
<CheckAmount>100</CheckAmount>
<FrontImage>R:\bin_simulated\Images\TempChequeImages\100f001.bmp</FrontImage>
<RearImage>R:\bin_simulated\Images\TempChequeImages\100r001.bmp</RearImage>
</Check>
<Check>
<CheckAmount>200</CheckAmount>
<FrontImage>R:\bin_simulated\Images\TempChequeImages\200f002.bmp</FrontImage>
<RearImage>R:\bin_simulated\Images\TempChequeImages\200r002.bmp</RearImage>
</Check>
</output>
Note:
The real problem here is the input. It should not be formatted this way. Things would be much easier if the person ahead of you did a proper job and supplied you with a well-structured XML, for example:
<ChqDepAppSrvChequeScanComplete>
<NumberOfCheques t="Int32">2</NumberOfCheques>
<Cheque>
<CourtesyAmount>100</CourtesyAmount>
<FrontImageFilename t="String">R:\bin_simulated\Images\TempChequeImages\100f001.bmp</FrontImageFilename>
<RearImageFilename t="String">R:\bin_simulated\Images\TempChequeImages\100r001.bmp</RearImageFilename>
<RefuseReason t="String">None</RefuseReason>
</Cheque>
<Cheque>
<CourtesyAmount>200</CourtesyAmount>
<FrontImageFilename t="String">R:\bin_simulated\Images\TempChequeImages\200f002.bmp</FrontImageFilename>
<RearImageFilename t="String">R:\bin_simulated\Images\TempChequeImages\200r002.bmp</RearImageFilename>
<RefuseReason t="String">None</RefuseReason>
</Cheque>
</ChqDepAppSrvChequeScanComplete>
with none of this numbered nodes nonsense.
I want to display only those orders which dont have OrderLineSource = YTR. All other should be displayed....
My Sample XML :
<Orders>
<Order>
<OrderID>34209649</OrderID>
<OrderStatus>checkout_complete</OrderStatus>
<Amount>32.93</Amount>
<OrderCreation>2014-02-08T00:00:03.00</OrderCreation>
<OrderCompletion>2014-02-08T00:00:03.00</OrderCompletion>
<CustomerGUID>303965683</CustomerGUID>
<CSMPurchaserGUID>0</CSMPurchaserGUID>
<Brand>TRFE</Brand>
<SourceECommerceSystem>Framework</SourceECommerceSystem>
<Currency>GBP</Currency>
<OrderChannel>Online</OrderChannel>
<TransactionSummary>
<TransactionID>2407065</TransactionID>
<MerchantReference>TEdV-5648-34209649</MerchantReference>
<CardCategory>Personal</CardCategory>
<CardScheme>VISA Debit</CardScheme>
<CardCountry>gbr</CardCountry>
<CardIssuer>sdfsdf sdf Bank asdf</CardIssuer>
<CardStartDate>0/0</CardStartDate>
<CardExpiryDate>2016/08</CardExpiryDate>
<Amount>32.93</Amount>
<Currency>GBP</Currency>
<CardPAN>************4585</CardPAN>
<Created>2014-02-07T23:56:48</Created>
<Updated>2014-02-08T00:00:03</Updated>
<ResponseStatusCode>1</ResponseStatusCode>
<ResponseStatusReason>FULFILLED OK</ResponseStatusReason>
<HostedPageIdentifier>dsfasdf-ee85-4afa-bb6a-0afc6dc99896</HostedPageIdentifier>
<HostedPageURL>https://hps.datacash.com/hps/</HostedPageURL>
<PaymentStatus>Paid</PaymentStatus>
<PaymentType>Debit Card</PaymentType>
<NameOnCard>Miss L J adsf</NameOnCard>
<DataCashRef>56456456454</DataCashRef>
<MerchantID>545646</MerchantID>
<ThreeDCard>1</ThreeDCard>
<ThreeDRequested>1</ThreeDRequested>
<IPAddress>127.89.560.1</IPAddress>
</TransactionSummary>
<OrderLine>
<OrderLineID>84598837</OrderLineID>
<OrderID>34209649</OrderID>
<OrderLineLabel>GAREGSBV</OrderLineLabel>
<OrderLineSource>GHR</OrderLineSource>
<Quantity>1</Quantity>
<UnitPrice>32.93</UnitPrice>
<Total>32.93</Total>
<SKUCode>P0032</SKUCode>
<Title>Miss.</Title>
<FirstName>ertwer</FirstName>
<FamilyName>sdaf</FamilyName>
<DateOfBirth>1984-05-30</DateOfBirth>
<Email>sdfasdfa#hotmail.com</Email>
<Mobile>645646454</Mobile>
<PostChannel>0</PostChannel>
<TelephoneChannel>0</TelephoneChannel>
<EmailChannel>0</EmailChannel>
<TextAndOtherChannel>0</TextAndOtherChannel>
<BuildingNumber>27</BuildingNumber>
<AddressLine1>27</AddressLine1>
<AddressLine2>dsfasdf Road</AddressLine2>
<Town>London</Town>
<Country>sdfasdf er</Country>
<Postcode>KL7 2NS</Postcode>
<AddressValidated>1</AddressValidated>
<HKPolicy>
<PolicyNum>PP01754397</PolicyNum>
<ProductDescription>sadfsadfasdfgasdg</ProductDescription>
<CoverTypeDesc>Individual</CoverTypeDesc>
<SingleParentFamilyFlag>0</SingleParentFamilyFlag>
<PolicyTypeRefID>S</PolicyTypeRefID>
<PolicyTypeDesc>Sinasdfnce</PolicyTypeDesc>
<TierDesc>Classic</TierDesc>
<DestinationDesc>Worldwide including USA, Canada, Caribbean</DestinationDesc>
<TotalTravellers>1</TotalTravellers>
<NumOfAdults>1</NumOfAdults>
<NumOfUnder18>0</NumOfUnder18>
<PolicyStartDate>2014-02-08</PolicyStartDate>
<PolicyEndDate>2014-02-12</PolicyEndDate>
<BaseCost>32.93</BaseCost>
<Commission>11.18</Commission>
<UpsoldInd>0</UpsoldInd>
<TierRefID>C</TierRefID>
<DestinationRefID>W2</DestinationRefID>
<CoverTypeRefID>I</CoverTypeRefID>
<AONToPostPolicy>yes</AONToPostPolicy>
<SalesChannel>0011002</SalesChannel>
<WhereYouHeardOfUs>Press advertising</WhereYouHeardOfUs>
<TIPOLTraveller>
<TravellerUUID>1864-1</TravellerUUID>
<PolicyNum>PI0e31754397</PolicyNum>
<Title>Miss</Title>
<FirstName>sdfsf</FirstName>
<FamilyName>sdfsdf</FamilyName>
<DateOfBirth>1984-05-30</DateOfBirth>
<AgeBand>1864</AgeBand>
<DependentFlag>0</DependentFlag>
</TIPOLTraveller>
</TIPOLPolicy>
</OrderLine>
<OrderCustomerDetails>
<Title nil="true" />
<FirstName nil="true" />
<SecondName nil="true" />
<FamilyName nil="true" />
<DateOfBirth nil="true" />
<Email nil="true" />
<Telephone nil="true" />
<Mobile nil="true" />
<Gender nil="true" />
<PostChannel nil="true" />
<TelephoneChannel nil="true" />
<EmailChannel nil="true" />
<TextAndOtherChannel nil="true" />
<BuildingNumber>27</BuildingNumber>
<AddressLine1>27</AddressLine1>
<AddressLine2>asdfa Road</AddressLine2>
<Town>asdfasdf</Town>
<Country>United dsf</Country>
<Postcode>KH9 2NS</Postcode>
<AddressValidated>1</AddressValidated>
</OrderCustomerDetails>
</Order>
<Order>
<OrderID>34209674</OrderID>
<OrderStatus>checkout_complete</OrderStatus>
<Amount>11.13</Amount>
<OrderCreation>2014-02-08T00:08:40.00</OrderCreation>
<OrderCompletion>2014-02-08T00:08:40.00</OrderCompletion>
<CustomerGUID>303965688</CustomerGUID>
<CSMPurchaserGUID>0</CSMPurchaserGUID>
<Brand>TRFDS</Brand>
<SourceECommerceSystem>Framework</SourceECommerceSystem>
<Currency>GBP</Currency>
<OrderChannel>Online</OrderChannel>
<TransactionSummary>
<TransactionID>8115032</TransactionID>
<MerchantReference>JHF-0800-34209674</MerchantReference>
<CardCategory>Personal</CardCategory>
<CardScheme>VISA Debit</CardScheme>
<CardCountry>gbr</CardCountry>
<CardIssuer>Unknown</CardIssuer>
<CardStartDate>0/0</CardStartDate>
<CardExpiryDate>2016/09</CardExpiryDate>
<Amount>11.13</Amount>
<Currency>GBP</Currency>
<CardPAN>************4849</CardPAN>
<Created>2014-02-08T00:08:00</Created>
<Updated>2014-02-08T00:08:40</Updated>
<ResponseStatusCode>1</ResponseStatusCode>
<ResponseStatusReason>FULFILLED OK</ResponseStatusReason>
<HostedPageIdentifier>f3306487-d6ea-4200-9eea-99b1d6832a2e</HostedPageIdentifier>
<HostedPageURL>https://hps.dat.com/hps/</HostedPageURL>
<PaymentStatus>Paid</PaymentStatus>
<PaymentType>Debit Card</PaymentType>
<NameOnCard>Miss Jor </NameOnCard>
<DataCashRef>380010093738013</DataCashRef>
<MerchantID>21877049</MerchantID>
<ThreeDCard>1</ThreeDCard>
<ThreeDRequested>1</ThreeDRequested>
<IPAddress>86..25640.99</IPAddress>
</TransactionSummary>
<OrderLine>
<OrderLineID>84598874</OrderLineID>
<OrderID>34209674</OrderID>
<OrderLineLabel>3-1008617753325</OrderLineLabel>
<OrderLineSource>YTR</OrderLineSource>
<Quantity>1</Quantity>
<UnitPrice>11.13</UnitPrice>
<Total>11.13</Total>
<Title>Miss.</Title>
<FirstName>Jordan</FirstName>
<SecondName>oirut</SecondName>
<FamilyName>dfgsdfgs</FamilyName>
<Email>dfgsdfg#hotmail.com</Email>
<Mobile>654756464</Mobile>
<PostChannel>0</PostChannel>
<TelephoneChannel>0</TelephoneChannel>
<EmailChannel>0</EmailChannel>
<TextAndOtherChannel>0</TextAndOtherChannel>
<BuildingNumber>12</BuildingNumber>
<AddressLine1>12</AddressLine1>
<AddressLine2>sfgsdfg End Gardens</AddressLine2>
<Town>HEMEL sfgaefa</Town>
<Country>adf dgfsdfg</Country>
<Postcode>HP1 1SN</Postcode>
<OrderLineDetail>
<NameValuePair>
<Name>dfgsdfg</Name>
<Value>628</Value>
</NameValuePair>
<NameValuePair>
<Name>NameOnCard</Name>
<Value>adsfgasdgf Piper</Value>
</NameValuePair>
<NameValuePair>
<Name>DateOnCard</Name>
<Value>2014-02-05</Value>
</NameValuePair>
<NameValuePair>
<Name>CustomsOrSurcharge</Name>
<Value>CUSTOMS CHARGE TO PAY</Value>
</NameValuePair>
</OrderLineDetail>
</OrderLine>
<OrderCustomerDetails>
<Title>Miss.</Title>
<FirstName>Jordan</FirstName>
<SecondName>asdgfasdgf</SecondName>
<FamilyName nil="true" />
<DateOfBirth />
<Email>adfadf#hotmail.com</Email>
<Telephone />
<Mobile>adfasdf</Mobile>
<Gender nil="true" />
<PostChannel nil="true" />
<TelephoneChannel nil="true" />
<EmailChannel nil="true" />
<TextAndOtherChannel nil="true" />
<BuildingNumber>12</BuildingNumber>
<AddressLine1>12</AddressLine1>
<AddressLine2>adfasdf End Gardens</AddressLine2>
<Town>adsfasdf HEMPSTEAD</Town>
<Country>United asdfasdf</Country>
<Postcode>asd 1SN</Postcode>
</OrderCustomerDetails>
</Order>
</Orders>
I tried using XSLT :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- Orders -->
<xsl:template match="/*">
<xsl:element name="Orders">
<xsl:apply-templates select="./Order" />
</xsl:element>
</xsl:template>
<!-- Orders > Order -->
<xsl:template match="/Order">
<xsl:variable name="IsValid">
<xsl:call-template name="HasOrIsValidPOLine" />
</xsl:variable>
<xsl:if test="$IsValid='VALID'"> <!-- only display the order if there's a valid line under it-->
<xsl:element name="Order">
<xsl:apply-templates select=".//VORNR" />
</xsl:element>
</xsl:if>
</xsl:template>
<!-- Part Order List > Part Order > Operational BO Number -->
<xsl:template match="//VORNR">
<xsl:element name="./Order">
<xsl:apply-templates select="node()|#*"/>
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<xsl:template name="HasOrIsValidPOLine">
<xsl:choose>
<xsl:when test="./OrderLineSource/text() != 'YTR'">VALID</xsl:when>
<xsl:otherwise>INVALID</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Can you provide me the solution or let me know where I am going wrong
First, your sample XML is not well-formed: It contains a closing </TIPOLPolicy> tag that doesn't match the starting <HKPolicy> tag. Change that to </HKPolicy> first.
After that, the following XSLT 1.0 does what you want:
<?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"/>
<!-- Identity transform -->
<!-- Default priority 0 for root node and -0.5 for the rest -->
<xsl:template match="/ | node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
<!-- Do nothing for Order elements whose OrderLine/OrderLineSource equals 'YTR' -->
<!-- Default priority 0.5 -->
<xsl:template match="Order[OrderLine/OrderLineSource = 'YTR']"/>
</xsl:stylesheet>
It makes use of the identity transform and different default priorities: The identity transform with a lower default priority copies the input to the output unless another template with a higher priority exists for a given input match. This is the case for Order elements whose OrderLine/OrderLineSource descendant contains the text value 'YTR'. Due to its higher default priority, the more specific template takes precedence over the identity transform. Since the template doesn't produce any output, any matching Order elements are removed from the output.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Order[OrderLine/OrderLineSource[string() = 'YTR']]"/>
</xsl:stylesheet>
I am trying to convert following xml into other xml but I am not getting the values for xCoordinate and yCoordinate. I would like to convert the structure from source - XML to Target-XML where the goocodes will match and the result would be assigned to x and y.
Source - XML
<?xml version="1.0"?>
<AddressResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" errorCode="0" errorDescription="">
<wrappedResultList xmlns="http://xlocate.xserver.ptvag.com">
<ResultAddress city="Amsterdam" city2="" country="NL" houseNumber="" postCode="1***" state="Noord-Holland" street="" adminRegion="Amsterdam" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="100">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="4.89327999999999" y="52.373090000000005" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
<ResultAddress city="Amsterdam-Zuidoost" city2="" country="NL" houseNumber="" postCode="110*" state="Noord-Holland" street="" adminRegion="Amsterdam" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="80">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="4.9513699999999838" y="52.316199999999988" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
<ResultAddress city="Nieuw-Amsterdam" city2="" country="NL" houseNumber="" postCode="7833" state="Drenthe" street="" adminRegion="Emmen" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="80">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="6.8528699999999994" y="52.716139999999982" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
</wrappedResultList>
</AddressResponse>
Target - XML
<GeoCodeResponse>
<geocordinate>
<xCordinate>4.89327999999999</xCordinate>
<yCordinate>52.716139999999982</yCordinate>
</geocordinate>
</GeoCodeResponse>
XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xl="http://xlocate.xserver.ptvag.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://common.xserver.ptvag.com" exclude-result-prefixes="xl xsi xsd cm" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<GeoCodeResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<geocordinate xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<xsl:for-each select="AddressResponse/xl:wrappedResultList/xl:ResultAddress">
<xsl:sort select="#xl:totalScore" order="descending" data-type="number"/>
<xsl:if test="position()= 1">
<xCordinate> <xsl:value-of select="/xl:coordinates/cm:point/cm:x" /></xCordinate>
<yCordinate> <xsl:value-of select="/xl:coordinates/cm:point/cm:y" /></yCordinate>
</xsl:if>
</xsl:for-each>
</geocordinate>
</GeoCodeResponse>
</xsl:template>
</xsl:stylesheet>
Please help what could be done in above xslt.
You were almost there. The coordinates are attributes, not nodes.
change it into this:
<xsl:if test="position()= 1">
<xCordinate>
<xsl:value-of select="xl:coordinates/cm:point/#x" />
</xCordinate>
<yCordinate>
<xsl:value-of select="xl:coordinates/cm:point/#y" />
</yCordinate>
</xsl:if>
You are also referencing the coordinates node from the root, but it should be relative. I changed /xl:coordinaties into xl:coordinates
When I try to recursive sum an attributes from multiple nodes, it's gluing like string :(
XML-file (second mileage-node include first mileage-node)
<mileage value="15000">
<operation title="Replacing the engine oil" cost="500" />
<sparepart title="Oil filter" cost="250" />
<sparepart title="Motor oil" cost="1050" />
</mileage>
<mileage value="30000">
<repeating mileage="15000" />
<operation title="Replacement of spark" cost="1200" />
</mileage>
XSL-template
<xsl:template match="mileage[#value]">
<xsl:param name="sum" select="number(0)" />
<xsl:variable name="milinkage"><xsl:value-of select="number(repeating/#mileage)" /></xsl:variable>
<xsl:apply-templates select="parent::*/mileage[#value=$milinkage]"><xsl:with-param name="sum" select="number($sum)" /></xsl:apply-templates>
<xsl:value-of select="number(sum(.//#cost))"/> <!-- + number($sum) -->
</xsl:template>
Glued result is 18001200, but I want see 3000 (1800 + 1200)
Please tell me what is wrong here?
Thanx!
Remove the dot and you will always see 3000 because all #costs (independent from starting point) will be summed.
<xsl:value-of select="number(sum(//#cost))"/> <!-- + number($sum) -->
Output will look like this: 30003000
But I assume that something is wrong with your approach. When you call a template recursive then the output will also will be printed as much as the template calls itself in your case. You need to print out the result at the end of your recursion
Given this input:
<root>
<mileage value="15000">
<operation title="Replacing the engine oil" cost="500" />
<sparepart title="Oil filter" cost="250" />
<sparepart title="Motor oil" cost="1050" />
</mileage>
<mileage value="30000">
<repeating mileage="15000" />
<operation title="Replacement of spark" cost="1200" />
</mileage>
</root>
and using this xslt:
<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="/">
<xsl:apply-templates select="root"/>
</xsl:template>
<xsl:template match="root">
<xsl:apply-templates select="mileage[#value=30000]"/>
</xsl:template>
<xsl:template match="mileage[#value]">
<xsl:param name="sum" select="number(0)" />
<xsl:variable name="milinkage"><xsl:value-of select="number(repeating/#mileage)" /></xsl:variable>
<xsl:variable name="newsum">
<xsl:value-of select="number(sum(.//#cost)) + $sum"/>
</xsl:variable>
<xsl:apply-templates select="parent::*/mileage[#value=$milinkage]"><xsl:with-param name="sum" select="number($newsum)" /></xsl:apply-templates>
<xsl:if test="not(parent::*/mileage[#value=$milinkage])">
<xsl:value-of select="$newsum"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
gives the correct result: 3000
You need xmlns:exsl="http://exslt.org/common"
<xsl:template match="/">
<xsl:variable name="nodes">
<xsl:apply-templates select="root/mileage[position()=last()]"/>
</xsl:variable>
<xsl:copy-of select="sum(exsl:node-set($nodes)/*[#cost]/#cost)"/>
</xsl:template>
<xsl:template match="mileage">
<xsl:copy-of select="*[#cost]"/>
<xsl:apply-templates select="../mileage[#value=current()/repeating/#mileage]"/>
</xsl:template>`
<statisticItems>
<statisticItem id="1" frontendGroupId="2336" caseId="50264" />
<statisticItem id="2" frontendGroupId="2336" caseId="50264" />
<statisticItem id="3" frontendGroupId="2337" caseId="50265" />
<statisticItem id="4" frontendGroupId="2337" caseId="50266" />
<statisticItem id="5" frontendGroupId="2337" caseId="50266" />
</statisticItems>
<?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" omit-xml-declaration="yes"/>
<xsl:key name="statistic-by-frontendGroupId" match="statisticItem" use="#frontendGroupId" />
<xsl:for-each select="statisticItems/statisticItem[count(.|key('statistic-by-frontendGroupId', #frontendGroupId)[1]) = 1]">
<xsl:value-of select="#frontendGroupId"/>
</xsl:for-each>
What i have done so fare is to go through all distict frontendGroupIds. What i would like to do now is to do a count of all the distict caseIds for each distict frontendGroupId but i cant seem to make that work. Can someone help me here plz?
You were close:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:key
name="statistic-by-frontendGroupId"
match="statisticItem"
use="#frontendGroupId"
/>
<xsl:template match="statisticItems">
<xsl:for-each select="
statisticItem[
count(
. | key('statistic-by-frontendGroupId', #frontendGroupId)[1]
) = 1
]
">
<xsl:value-of select="#frontendGroupId"/>
<xsl:value-of select="' - '"/>
<!-- simple: the item count is the node count of the key -->
<xsl:value-of select="
count(
key('statistic-by-frontendGroupId', #frontendGroupId)
)
"/>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This results in:
2336 - 2
2337 - 3
EDIT - Oh, I see you want the distinct count within the group. This would be:
<!-- the other key from the above solution is still defined -->
<xsl:key
name="kStatisticItemByGroupAndCase"
match="statisticItem"
use="concat(#frontendGroupId, ',', #caseId)"
/>
<xsl:template match="statisticItems">
<xsl:for-each select="
statisticItem[
count(
. | key('kStatisticItemByGroup', #frontendGroupId)[1]
) = 1
]
">
<xsl:value-of select="#frontendGroupId"/>
<xsl:value-of select="' - '"/>
<xsl:value-of select="
count(
key('kStatisticItemByGroup', #frontendGroupId)[
count(
. | key('kStatisticItemByGroupAndCase', concat(#frontendGroupId, ',', #caseId))[1]
) = 1
]
)
"/>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
Which looks (admittedly) a bit frightening. It outputs:
2336 - 1
2337 - 2
The core expression:
count(
key('kStatisticItemByGroup', #frontendGroupId)[
count(
. | key('kStatisticItemByGroupAndCase', concat(#frontendGroupId, ',', #caseId))[1]
) = 1
]
)
boils down to:
Count the nodes from "key('kStatisticItemByGroup', #frontendGroupId)" that fulfill the following condition: They are the first in their respective "kStatisticItemByGroupAndCase" group.
Looking closely, you will find that this is no more complicated than what you already do. :-)
EDIT: One last hint. Personally, I find this a lot more expressive than the above expressions, because it emphasizes node equality a lot more than the "count(.|something) = 1" approach:
count(
key('kStatisticItemByGroup', #frontendGroupId)[
generate-id()
=
generate-id(
key('kStatisticItemByGroupAndCase', concat(#frontendGroupId, ',', #caseId))[1]
)
]
)
The result is the same.
You are attempting to sort via the dreaded 'MUENCHIAN' method - something i've found so confusing that is not worth trying - so i worked out my own method.
It uses two transformations instead of one.
The first sorts the data into the right order based on your grouping requirements -- your sample data is already in the right order so i'll leave it out of this explanation( ask if you want help here)
The second transformation does the grouping simply by comparing one node to the next:
<?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="statisticItems">
<groupedItem>
<xsl:apply-templates select="statisticItem"></xsl:apply-templates>
</groupedItem>
</xsl:template>
<xsl:template match="statisticItem">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:apply-templates select="#frontendGroupId" />
</xsl:when>
<xsl:when test="#frontendGroupId!=preceding-sibling::statisticItem[1]/#frontendGroupId">
<xsl:apply-templates select="#frontendGroupId" />
</xsl:when>
</xsl:choose>
<xsl:apply-templates select="#caseId" />
</xsl:template>
<xsl:template match="#frontendGroupId">
<group>
<xsl:variable name="id" select="." ></xsl:variable>
<xsl:attribute name="count">
<xsl:value-of select="count(//statisticItem/#frontendGroupId[.=$id])"/>
</xsl:attribute>
<xsl:value-of select="." />
</group>
</xsl:template>
<xsl:template match="#caseId">
<value>
<xsl:value-of select="." />
</value>
</xsl:template>
</xsl:stylesheet>
With this method you can go several groups deep and still have maintainable code.