Re: [xsl] expand conditional variable in xsl:key match

Subject: Re: [xsl] expand conditional variable in xsl:key match
From: Xiaocun Xu <xiaocunxu@xxxxxxxxx>
Date: Sat, 21 Jun 2003 10:43:37 -0700 (PDT)
Hi, Wendell:

  Thanks for your input.  
  Yes, there are performance concerns, and the way we
current dealt with XSLT jobs is to treat them as async
job and sent it off to be processed in a separate job
server.  This strategy has been working well for us
since it alleviates the load on the main transaction
server.
  I know it is not a good practice to lock myself
Saxon6.0.2 for this one key feature (I agree with you
that the ability to use variables in xsl:key match/use
is really a bug in XSLT1.0 conformant processor, but a
key feature in XSLT2.0).  But on the other hand, this
would not need to be changed once I upgraded to
XSLT2.0.  Given how stable Saxon6.0.2 has been and how
little time I have, this could be a reasonable risk to
take at this time.  Before that decision is made, it
is certainly good to consider all the options.  
  To see if there another way to resolve my problem,
below is my original problem, described with source
XML, target XML, my code and explanation in that
order:

Source XML:
  <row row="12">
    <cell column="1">*Item Name</cell>
    <cell column="2">Item Unique ID</cell>
    <cell column="3">*Category Unique ID</cell>
    <cell column="4">*Item Type</cell>
    <cell column="5">*Minimum Desired Quantity</cell>
    <cell column="6">Lot Name</cell>
    <cell column="7">Description</cell>
  </row>
  <row row="13">
    <cell column="1">item1</cell>
    <cell column="2">item1</cell>
    <cell column="3">valves</cell>
    <cell column="4">single</cell>
    <cell column="5">1</cell>
    <cell column="6"></cell>
    <cell column="7">11</cell>
  </row>
  <row row="14">
    <cell column="1">item2</cell>
    <cell column="2">item2</cell>
    <cell column="3">valves</cell>
    <cell column="4">single</cell>
    <cell column="5">2</cell>
    <cell column="6">NEWLOT</cell>
    <cell column="7">NEWDESC</cell>
  </row>
  <row row="16">
    <cell column="1">*Bid Type</cell>
    <cell column="2">*Item Unique ID</cell>
    <cell column="3">Supplier Item Code</cell>
    <cell column="4">*Price Per Unit</cell>
    <cell column="5">Bid Code</cell>
    <cell column="6">Currency Code</cell>
    <cell column="7">Supplier Organization Code</cell>
  </row>

Target XML:
<Requisition RequisitionCode="Default"
RequisitionName="Default">
<LineItem LineItemName="item1" LineItemCode="item1"
LineItemCategoryCode="valves" LineItemType="single"
LineItemMinimumDesiredQuantity="1"
LineItemDescription="11"/>
</Requisition>
<Requisition RequisitionCode="NEWLOT"
RequisitionName="NEWLOT">
<LineItem LineItemName="item2" LineItemCode="item2"
LineItemCategoryCode="valves" LineItemType="single"
LineItemMinimumDesiredQuantity="2"
LineItemDescription="NEWDESC"/>
</Requisition>

My current code in Saxon6.0.2 with xsl:key match/use
contain variables:
	<xsl:variable name="LineItemHeader"
select="//row[cell[@column=1] = '*Item Name'][1]"/>
	<xsl:variable name="LineItemHeaderRow"
select="$LineItemHeader/@row"/>
	<xsl:variable name="BidHeader"
select="//row[cell[@column=1] = '*Bid Type'][1]"/>
	<!-- assume bid is the last possible section.  If bid
header non-existant, set it to the last row + 1 -->
	<xsl:variable name="BidHeaderRow">
		<xsl:choose>
			<xsl:when test="$BidHeader/@row &gt; 0">
				<xsl:value-of select="$BidHeader/@row"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="//row[last()]/@row + 1"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>	
	<xsl:variable name="LineItemLotColumn"
select="$LineItemHeader/cell[.='Lot Name']/@column"/>
	<xsl:key name="lineitemLotsKey" match="//row[@row
&gt; $LineItemHeaderRow and @row &lt; $BidHeaderRow]"
use="string(cell[@column=$LineItemLotColumn])"/>

	<!-- Lot (Requisitiion) section -->
	<xsl:template match="row" mode="Lot">
		<xsl:variable name="lotName"
select="string(cell[@column=$LineItemLotColumn])"/>
		<xsl:choose>
			<xsl:when test="string($lotName)">
				<xsl:element name="Requisition">
					<xsl:attribute
name="RequisitionCode"><xsl:value-of
select="$lotName"/></xsl:attribute>
					<xsl:attribute
name="RequisitionName"><xsl:value-of
select="$lotName"/></xsl:attribute>
					<!-- process each item within the non-default lot
-->
					<xsl:apply-templates
select="key('lineitemLotsKey', $lotName)"
mode="LineItem"/>
				</xsl:element>
			</xsl:when>
			<xsl:otherwise>
				<!-- Default lot is represented with empty string
or non-existing LineItemLotName attribute -->
				<xsl:element name="Requisition">
					<xsl:attribute
name="RequisitionCode">Default</xsl:attribute>
					<xsl:attribute
name="RequisitionName">Default</xsl:attribute>
					<!-- process each item within default lot -->
					<xsl:apply-templates
select="key('lineitemLotsKey', $lotName)"
mode="LineItem"/>
				</xsl:element>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

Explanation:
1. the source XML is generated with a generic Excel to
XML reader.  It simply read every row in a Excel
spreadsheet and write to a <row> element.  Therefore,
all the row id for each row could change depends on
how many rows are above it.
2. to find the start of each section, variables
LineItemHeaderRow and BidHeaderRow are declared.  For
the source XML given above, they would be 12 and 16,
respectively.  Note, the bid header row is optional,
therefore it is declared as a conditional variable. 
If <row row="16"> element did not exist, BioHeaderRow
would be the last row id + 1, which would be 15 in
this case.
3. a variable LineItemLotColumn is declared to find
the column where "Lot Name" is located.  This column
could also change between different files.
4. a key lineitemLotsKey id declared to match all rows
between LineItemHeaderRow and BidHeaderRow and use the
value in LineItemLotColumn cell.  Note, both the match
and use contains variables which is non-conform to
XSLT1.0, but somehow allowed by Saxon6.0.2, but not by
Saxon6.2.2/6.4.3/6.5.2.  This caused me unable to
upgrade to Saxon6.5.2.
5. a template on row would process the rows based on
the groups created by the key lineitemLotsKey.
6. other limitation worth reiterating is that the XSLT
processor I choose has to work with JDK1.3.1_07, which
is the latest JDK supported by WebLogic6.1.

Hope this provides all the necessary info, let me know
if there are any questions regarding this problem
statement.  Any suggestions would be very much
appreciated.

Thanks,
Xiaocun

--- Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> wrote:
> Xiaocun,
> 
> At 09:53 AM 6/18/2003, you wrote:
> >I see.  Looks like my options are:
> >1. investigate forward-walk
> >2. enhance incoming data (the current design is to
> >keep process prior to XSLT generic with no business
> >logic, this will have to break that)
> 
> Splitting the process in two could achieve this goal
> without having to 
> break your design principle all the way back. It
> should be able to pipeline 
> your transforms through Saxon using your copy of
> WebLogic, or even batch 
> process them. (Are there performance constraints?)
> 
> In fact, I'd propose that if you're trying to
> encapsulate your "business 
> logic" in XSLT, that eventually you'll be wanting to
> pipeline in any case. 
> (Although I should add that a nodeset() function or
> its equivalent -- the 
> application of processing result node sets that
> we'll be getting in XSLT 2 
> -- can be used to emulate a pipeline.)
> 
> >3. go back to Saxon6.0.2.  Somehow variable was
> >allowed in xsl:key match/use in that version, I had
> to
> >expand the variable out when I upgraded to
> Saxon6.5.2,
> >which is the cause of this problem I am having now.
> >When the variables are expanded out, the
> performance
> >went down drastically concurrently, which is
> another
> >reason I might decide to go back.
> >4. wait until WebLogic6.1 supports JDK1.4 and move
> up
> >to Saxon7.5.1 (this probably will never happen)
> >
> >Since we might want to skip WebLogic7.1, we seems
> >committed to WebLogic6.1 for an extended period,
> >therefore option #3 might be the most viable at
> this
> >time for me.
> 
> I wouldn't give up on the others. It's a pity to
> lock yourself into a 
> non-conformant version of a tool just for one
> "feature". :->
> 
> Could we please see your data again, with a concise
> restatement of the 
> problem and perhaps desired output? (Sorry.)
> 
> Cheers,
> Wendell
> 
> 
>
___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_
>      "Thus I make my own use of the telegraph,
> without consulting
>       the directors, like the sparrows, which I
> perceive use it
>       extensively for a perch." -- Thoreau
> 
> 
>  XSL-List info and archive: 
> http://www.mulberrytech.com/xsl/xsl-list
> 


__________________________________
Do you Yahoo!?
SBC Yahoo! DSL - Now only $29.95 per month!
http://sbc.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread