Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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
 
Old July 27th, 2010, 12:43 PM
Registered User
 
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default 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
 
Old July 27th, 2010, 12:57 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old July 27th, 2010, 01:37 PM
Registered User
 
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default

I am using XSLT1.0 but i have the flexibility to use XSLT2.0..the values are hard coded in XSLT.
 
Old July 27th, 2010, 01:47 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old July 27th, 2010, 01:50 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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:
test7 (July 27th, 2010)
 
Old July 27th, 2010, 01:53 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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:
test7 (July 27th, 2010)
 
Old July 27th, 2010, 04:32 PM
Registered User
 
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default

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
 
Old July 27th, 2010, 04:33 PM
Registered User
 
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
Default

Thanks Michael , i will try this one as well.





Similar Threads
Thread Thread Starter Forum Replies Last Post
XSL/XPATH namespace issue caltech XSLT 2 April 26th, 2010 11:31 AM
xsl:copy-of Issue DKatSSA BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition ISBN: 978-0-470-19274-0 8 November 19th, 2008 05:18 PM
performance issue with the xsl given here anboss XSLT 11 July 16th, 2008 03:05 AM
XSL Issue mickhughes XSLT 4 October 18th, 2007 08:29 AM
xsl:sort and IE 5.0 Issue babloo81 XSLT 1 March 17th, 2004 06:12 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.