 |
| 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 29th, 2010, 09:44 AM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Generate and Use UniqueId at two places in target XML
Hello All,
I need develop a XSLT and below is input and target. when the LocationId is mapped to target XML in StopDetails , need to generate a Unique Id for StopId, we have developed a custom Xpath function that would return unique ID so we are good until this part..But the problem is , the stop location needs to mapped to LineItems as well, when doing so, we need to map the same unique id generated above for the StopId..In the Target XML, these stop and lineietms elements are not in sequence, they are at different levels..so I need some kind of storing mechanism to store the UniqueId generated for Stops and use them same at LineItem level. I am not getting any thoughts on how to achieve this, Would appreciate your help on this.
Input XML
<Shipment>
<Stops>
<Stop>
<LocationId>XYZ123</LocationId>
</Stop>
<Stop>
<LocationId>XYZ345</LocationId>
</Stop>
<Stop>
<LocationId>XYZ567</LocationId>
</Stop>
</Stops>
</Shipment>
Target XML
<Root-element>
<StopDetails>
<Stop>
<StopId>111</StopId>
<LocationId>XYZ123</LocationId>
</Stop>
<Stop>
<StopId>112</StopId>
<LocationId>XYZ345</LocationId>
</Stop>
<Stop>
<StopId>113</StopId>
<LocationId>XYZ567</LocationId>
</Stop>
</StopDetails>
<!-- Many element here -->
<LineItems>
<Lineitem>
<id>item1</id>
<Stopdetails>
<Stop>
<StopId>111</StopId>
<LocationId>XYZ123</LocationId>
</Stop>
<Stop>
<StopId>112</StopId>
<LocationId>XYZ345</LocationId>
</Stop>
</Stopdetails>
</Lineitem>
<Lineitem>
<id>item2</id>
<Stopdetails>
<Stop>
<StopId>112</StopId>
<LocationId>XYZ345</LocationId>
</Stop>
<Stop>
<StopId>113</StopId>
<LocationId>XYZ567</LocationId>
</Stop>
</Stopdetails>
</Lineitem>
</LineItems>
</Root-element>
Thanks/Steve
|
|

July 29th, 2010, 09:54 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
One way would be to use generate-id() on the LocationId element to generate the unique identifier. But it you need control over the identifiers generated, change your function so it takes the LocationId as a parameter, and either hashes it, or remembers the values previously generated in a hashmap or similar.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

July 29th, 2010, 09:54 AM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
If you need to process the same elements twice (as you seem to do with Stop/LocationId) then I would expect you to achieve that using modes on your templates. And if you already have a function that computes an id I don't see why you can't call that function in templates with different modes.
Or what exactly prevents you from calling that function at different places in your stylesheet?
Of course if needed you could (at least with XSLT 2.0) easily do the first processing/mapping in a variable value and then process the contents of that variable where you already have the generated id. That might also need modes however.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

July 29th, 2010, 10:00 AM
|
|
Registered User
|
|
Join Date: Jul 2010
Posts: 6
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
The Xpath function invokes a database sequence so i cannot call the same function twice as it would return a different value. the business wants these Ids to be in sequence so we decided to use a DB sequence.
|
|

July 29th, 2010, 10:12 AM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
Do you use XSLT 2.0? Or XSLT 1.0 and your XSLT processor supports an extension function like exsl:node-set to convert a result tree fragment into a node-set? Then I think my second suggestion should do e.g.
Code:
<xsl:template match="/">
<xsl:variable name="temp1">
<xsl:apply-templates select="Shipment/Stops"/>
<!-- create StopDetails with those templates, callng your function -->
</xsl:variable>
<Root-element>
<xsl:copy-of select="$temp1/StopDetails"/>
<!-- then process the variable here to create line items e.g. -->
<xsl:apply-templates select="$temp1/StopDetails"/>
</Root-element>
</xsl:template>
<xsl:template match="Shipment/Stops">
<StopDetails>
<xsl:apply-templates/>
</StopDetails>
</xsl:template>
<xsl:template match="Shipment/Stops/Stop">
<xsl:copy>
<StopId><xsl:value-of select="foo:your-function()"/></StopId>
<xsl:copy-of select="LocationId"/>
</xsl:copy>
</xsl:template>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

July 29th, 2010, 11:10 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
>The Xpath function invokes a database sequence so i cannot call the same function twice
In a functional language, that's bad news. Turn it into a memo function by checking if it's been called before for a given argument, and if so, returning the same value.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
 |