[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: expand conditional variable in xsl:key match

Subject: Re: expand conditional variable in xsl:key match
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 23 Jun 2003 13:37:55 -0400
xslt1.0 grouping
Xiaocun,

I've looked at the code, and have one or two more questions.

The variables and key declaration appear at the top level (as indeed the key declaration must), which makes me wonder whether you need the key at all to do your grouping. Will there ever be more than one LineItemHeader row per document? Will all rows in the document that are *not* the LineItemHeader row or the BidHeader row be, necessarily, a LineItem Row?

If the answers are 'no' and 'yes' (and maybe even if not), could you get away with simply:

<xsl:key name="lineitemLotsKey"
match="row[not(cell[@column=1] = '*Item Name')
and not(cell[@column=1] = '*Bid Type')]"
use="string(cell[@column=//row[cell[@column=1] = '*Item Name'][1]/cell[.='Lot Name']/@column])"/>


since that's pretty much what your logic boils down to anyhow?

(If this declaration is hairy, that's mainly because you have to query into the tree multiple times to find out which column is your Item Name column. That's the kind of thing a two-step process would help with: a first pass would label things properly for a second pass to retrieve.)

Notice it's working around the problem by saying that grouping isn't actually required here: the key needs only to retrieve LineItem rows by the value of a particular cell.

If your data is more complex and you really do require grouping (and even if not), going to two or more passes would considerably simplify the processing. In the first pass you could group the rows and label the cells by what they actually are (instead of merely by their positions); the second transform could do the extraction and reporting.

I hope that helps--
Wendell

At 01:43 PM 6/21/2003, you wrote:
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


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


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



Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.