 |
| XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

July 27th, 2010, 12:43 PM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
XSL for-each issue
Hello,
I have this XML as input and need to generate an output element when the ShipmentStatusId equals to certain values..Let us say when the status equals to STATUS1 or STATUS5 or STATUS10, i need to produce an element in the target XML even if there are multiple statuses meets the condition . In the real world, we get around 100 statuses and I don't want to iterate through everyone , when the first match is found and wanted to come out of the loop and generate the target element. when I compare statuses, I need to compare only with the values after 'SBL.'..would appreciate your help on this.
<ShipmentResponseABM xmlns="http://xmlns.test.com/EnterpriseObjects/Core/Common/V1">
<ShipmentHeader>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS1</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS2</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS3</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS4</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS5</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS6</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS7</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS8</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS9</Id>
</ShipmentStatusId>
</ShipmentStatus>
<ShipmentStatus>
<ShipmentStatusId>
<Id>SBL.STATUS10</Id>
</ShipmentStatusId>
</ShipmentStatus>
</ShipmentHeader>
</ShipmentResponseABM>
Thanks/Steve
|
|

July 27th, 2010, 12:57 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
Do you use XSLT 1.0 or 2.0?
Do you want to provide those values you want to compare to in the form of a second XML document? Or how exactly do you provide those values to the stylesheet?
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

July 27th, 2010, 01:37 PM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
I am using XSLT1.0 but i have the flexibility to use XSLT2.0..the values are hard coded in XSLT.
|
|

July 27th, 2010, 01:47 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
I am not sure what the problem is, simply use substring-after e.g.
Code:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:cv1="http://xmlns.test.com/EnterpriseObjects/Core/Common/V1"
exclude-result-prefixes="cv1">
<xsl:template match="/">
<xsl:if test="cv1:ShipmentResponseABM/cv1:ShipmentHeader/cv1:ShipmentStatus[substring-after(cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS1' or substring-after(cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS5' or substring-after(cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS10']">
<!-- output here what you want to output if an element meeting the condition exists -->
</xsl:if>
</xsl:template>
</xsl:stylesheet>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

July 27th, 2010, 01:50 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
With XSLT 2.0 it is a bit shorter:
Code:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xpath-default-namespace="http://xmlns.test.com/EnterpriseObjects/Core/Common/V1>
<xsl:template match="/">
<xsl:if test="ShipmentResponseABM/ShipmentHeader/ShipmentStatus[substring-after(ShipmentStatusId/Id, 'SBL.') = ('STATUS1', 'STATUS5', 'STATUS10')]">
<!-- output here what you want to output if an element meeting the condition exists -->
</xsl:if>
</xsl:template>
</xsl:stylesheet>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
Last edited by Martin Honnen; July 27th, 2010 at 01:53 PM..
Reason: correcting version attribute
|
|
The Following User Says Thank You to Martin Honnen For This Useful Post:
|
|
|

July 27th, 2010, 01:53 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
I would recommend setting up the values like this:
Code:
<xsl:variable name="specials">
<v>STATUS1</v>
<v>STATUS5</v>
<v>STATUS8</v>
</xsl:variable>
<xsl:key name="k" match="v" use="."/>
and then you can test whether a particular value $X is in the list efficiently using
Code:
<xsl:if test="key('k', $X, $specials)"/>
The 3-argument form of the key() function is XSLT 2.0 only.
An alternative is to declare the key as
Code:
<xsl:key name="k" match="/" use="$specials//v"/>
and then you can use
Code:
<xsl:if test="key('k', $X)"/>
but that's a bit obscure for most people's taste.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
The Following User Says Thank You to mhkay For This Useful Post:
|
|
|

July 27th, 2010, 04:32 PM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Thanks martin, this worked for me.
The mistake i was doing was
<xsl:template match="/">
<xsl:if test="substring-after(cv1:ShipmentResponseABM/cv1:ShipmentHeader/cv1:ShipmentStatus/cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS1' or substring-after(cv1:ShipmentResponseABM/cv1:ShipmentHeader/cv1:ShipmentStatus/cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS5' or substring-after(cv1:ShipmentResponseABM/cv1:ShipmentHeader/cv1:ShipmentStatus/cv1:ShipmentStatusId/cv1:Id, 'SBL.') = 'STATUS10'">
<!-- output here what you want to output if an element meeting the condition exists -->
</xsl:if>
Thanks/Steve
|
|

July 27th, 2010, 04:33 PM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Thanks Michael , i will try this one as well.
|
|
 |