XML Editor
Sign up for a WebBoard account Sign Up Keyword Search Search More Options... Options
Chat Rooms Chat Help Help News News Log in to WebBoard Log in Not Logged in
Show tree view Topic
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Postnext
James DurningSubject: Efficient merge and split
Author: James Durning
Date: 19 Oct 2004 12:59 PM
First of all, I know about xsl:document(), (XSLT 1.1) and xsl:result-document(href='') (XSLT 2.0) and xt:document etc...
I've got 2 documents which I am merging and then splitting off into multiple documents. Here's an abstraction of the code:

Source file:
<library>
<book key="1" author="Dickens" other="F"/>
<book key="2" author="Verne" other="T">
</library>

Lookup table:
<lookup>
<row key="1" globalid="562"/>
<row key="49" globalid="143"/>
<row key="2" globalid="322"/>
</lookup>
---
Desired Output 1
<output1>
<book globalid="562" author="Dickens">
<book globalid="322" author="Verne">
</output1>

Output2
<output2>
<book globalid="562" other="F">
<book globalid="322" other="T">
</output2>
---
I can get either of these files seperately by using seperate xslt files, but what I want is something that minimizes the lookup. Eg, what I have now:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:variable name="LOOKUP" select=document("'C:/xslt/lookuptable.xml'")/lookup/>
<xsl:template match="/library">
<output1>
<xsl:for-each select="book">
<book>
<xsl:variable name="KEY" select="@key"/>
<xsl:variable name="ID" select="$LOOKUP/row[$KEY=@key]/globalid"/><!-- LOOKUP HERE -->
<xsl:attribute name="globalid"><xsl:value-of select="$ID"/></xsl:attribute>
<xsl:attribute name="author"><xsl:value-of select="@author"/></xsl:attribute>
</book>
</xsl:for-each>
</output1>
</xsl:template>
</xsl:output>
</xsl:stylesheet>

Output2 is the same except I change 'output1' elements to 'output2', and 'author' with 'other' everywhere.
I would like someway to minimize the lookup, eg do it once per book. Is there any way to do this without creating a secondary xml document? I want to use xsl:document (with SAXON) if possible.

What I tried: inside for loop, using <xsl:document href="output2">global id = id, other = @other, ...etc.
but then the xsl:document clears the document each time, so I wind up with one element.

I know this is a hard question. Thank you to anyone who has any ideas not yet mentioned.

Postnext
Ivan PedruzziSubject: Efficient merge and split
Author: Ivan Pedruzzi
Date: 19 Oct 2004 11:09 PM
Hi James,

The following solution reduces the number of look-up and
should improve performance if your look-up table is large.

The solution is based on XSLT 1.1 and has been tested with Saxon 6.5.3
It can be easly translate to XSLT 2.0 using xsl:result-document.

Hope this helps
Ivan

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:key name="id" match="/lookup/row" use="@key"/>

<xsl:template match="library">

<xsl:variable name="merged">
<library>
<xsl:for-each select="book">
<xsl:variable name="key" select="@key"/>
<xsl:variable name="author" select="@author"/>
<xsl:variable name="other" select="@other"/>
<xsl:for-each select="document('library_lookup.xml')">
<xsl:variable name="gid" select="key('id', $key)/@globalid"/>
<output1>
<book>
<xsl:copy-of select="$gid"/>
<xsl:attribute name="author">
<xsl:value-of select="$author"/>
</xsl:attribute>
</book>
</output1>
<output2>
<book>
<xsl:copy-of select="$gid"/>
<xsl:attribute name="author">
<xsl:value-of select="$other"/>
</xsl:attribute>
</book>
</output2>
</xsl:for-each>
</xsl:for-each>
</library>
</xsl:variable>

<xsl:call-template name="toFile">
<xsl:with-param name="filename" select="'output1.xml'"/>
<xsl:with-param name="source" select="$merged/library/output1/book"/>
</xsl:call-template>

<xsl:call-template name="toFile">
<xsl:with-param name="filename" select="'output2.xml'"/>
<xsl:with-param name="source" select="$merged/library/output2/book"/>
</xsl:call-template>

<xsl:text>Done!</xsl:text>

</xsl:template>

<xsl:template name="toFile">
<xsl:param name="filename"/>
<xsl:param name="source"/>
<xsl:document href="{$filename}" method="xml" indent="yes">
<library>
<xsl:for-each select="$source">
<xsl:copy-of select="."/>
</xsl:for-each>
</library>
</xsl:document>
</xsl:template>

</xsl:stylesheet>

Postnext
James DurningSubject: Efficient merge and split
Author: James Durning
Date: 20 Oct 2004 04:44 PM
Originally Posted: 20 Oct 2004 04:43 PM
Wow, Thank you! I had thought using the xsl:variable like that was restricted to xslt 2.0, but I guess Saxon implemented it in previous versions. Intriguing. One more, is there any way to generalize the xsl:key element to match 2 or more different type of keys at once?

Posttop
Ivan PedruzziSubject: Efficient merge and split
Author: Ivan Pedruzzi
Date: 20 Oct 2004 05:03 PM
James

RTF (result tree fragment) are part of of the XSLT 1.0 type system
but the language didn't allow to convert them to node-set so
most the implementation have an extention function for this purpose.

Starting from XSLT 1.1 RTF are coerce to node-set automatically.

xsl:key does *not* allow variables, but you can define as many as you like

Ivan

 
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Download A Free Trial of Stylus Studio 6 XML Professional Edition Today! Powered by Stylus Studio, the world's leading XML IDE for XML, XSLT, XQuery, XML Schema, DTD, XPath, WSDL, XHTML, SQL/XML, and XML Mapping!  
go

Log In Options

Site Map | Privacy Policy | Terms of Use | Trademarks
Stylus Scoop XML Newsletter:
W3C Member
Stylus Studio® and DataDirect XQuery ™are from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2011 All Rights Reserved.