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 May 29th, 2007, 05:24 PM
Authorized User
 
Join Date: May 2007
Posts: 79
Thanks: 0
Thanked 0 Times in 0 Posts
Default comparing nodeset

I want to compare two nodesets using several classifiers. If there is a match on each classifier, return true.

The classifiers are identified in two levels of delimited pairs:

source1,target1;source2,target2;source3,target3

If I knew how many classifiers I was dealing with, I could use (ignoring context of each cell):

test="row[ cell[@type=source1] = cell[@type=target1] ]"/>

Is there an efficient way to dynamically determine a match depending on a variable number of comparisons?
 
Old May 29th, 2007, 05:33 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Sorry, I don't understand the problem from this description. Please show an example of the input to your transformation and the desired output.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old May 30th, 2007, 08:44 AM
Authorized User
 
Join Date: May 2007
Posts: 79
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Sorry about the incomplete post.

Primary XML Input:

<row index="1">
   <cell name="instruction"/>
   <cell name="document">file.doc</cell>
   <cell name="path">Archive/documents/</cell>
</row>

Secondary XML Input:

<row index="40">
   <cell name="instruction"/>
   <cell name="file">file.doc</cell>
   <cell name="location">Archive/documents/</cell>
</row>

XSLT:

The following will be passed in as a parameter. The number of classifier pairs is unknown:
<xsl:param name="classifiers">document:file,path:location</xsl:param>

What I need to do:

Locate (and capture) row in the secondary input that maps to the primary input using the unknown number of classifiers. I am looking for the most efficient way to solve this problem.

Any help is appreciated. Thanks.

 
Old May 30th, 2007, 09:48 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I'm not sure why you're using a non-XML syntax for the parameter. It would simplify the problem to use an XML syntax; if you have to parse the string first to produce the XML, we can handle that as a separate problem.

But I still need to ask more questions about the requirement.

Are there multiple rows in either or both of the inputs?

Are you looking for a match of a row in input2 with any row in input1, or with a specific row in input1? If the latter, what's the correspondence between the rows that must match: by position? by value of the name in the first cell?

When document:file appears as a classifier, what exactly does it mean? That the cell named document in input1 has to have the same value as the cell named file in input2? Do these cells have to be in the same position within the row? What happens if either row doesn't have a cell with the given name?

What's the significance of cells (such as "instruction" in your example) for which there is no classifier? Are they simply ignored, or do they have to match in both rows?

Finally, this is going to be a lot easier in XSLT 2.0 (most things are). Do you have any technology constraints?

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old May 30th, 2007, 10:29 AM
Authorized User
 
Join Date: May 2007
Posts: 79
Thanks: 0
Thanked 0 Times in 0 Posts
Default

There are multiple rows in both XML documents and I am looking for a match between a row in input1 and a row in input2. The classifiers define the mapping scheme. So, in the following XML, the rows match because

$input1/cell[@name='document'] = $input2/cell[@name='file']
and
$input1/cell[@name='path'] = $input2/cell[@name='location']

Primary XML Input:

<row index="1">
   <cell name="instruction"/>
   <cell name="document">file.doc</cell>
   <cell name="path">Archive/documents/</cell>
</row>

Secondary XML Input:

<row index="40">
   <cell name="instruction"/>
   <cell name="file">file.doc</cell>
   <cell name="location">Archive/documents/</cell>
</row>

The is an unknown number of classifiers, so the following XML might be valid:


<row index="1">
   <cell name="instruction"/>
   <cell name="type">word file</cell>
   <cell name="document">file.doc</cell>
   <cell name="path">Archive/documents/</cell>
</row>

Secondary XML Input:

<row index="40">
   <cell name="instruction"/>
   <cell name="filetype">word file</cell>
   <cell name="file">file.doc</cell>
   <cell name="location">Archive/documents/</cell>
</row>

In which case the following classifiers would be passed:
document:file,path:location,type:filetype

I am capturing the classifiers in an XML nodeset:

<xsl:variable name="MAPPING_classifiers">
<Mapping_Classifiers>
<xsl:for-each select="$tokenize_classifiers">
<xsl:variable name="tokenize_further" select="tokenize(.,':')"/>
<xsl:variable name="index"><xsl:value-of select="index-of($tokenize_classifiers,.)" /></xsl:variable>
  <xsl:element name="classifier">
    <xsl:attribute name="index">
      <xsl:value-of select="$index" />
    </xsl:attribute>
    <xsl:for-each select="$tokenize_further">
      <xsl:element name="class">
        <xsl:value-of select="." />
      </xsl:element>
    </xsl:for-each>
  </xsl:element>
</xsl:for-each>
</Mapping_Classifiers>
</xsl:variable>



 
Old May 30th, 2007, 12:35 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Thanks. So it looks something like

$doc2//row[
   some $r in $doc1//row satisfies
     every $c in $MAPPING_classifiers/classifier satisfies
      (./cell[@name=$c/class[2]] and $r/cell[@name=$c/class[1]])]

Incidentally, I would write this:

<xsl:variable name="MAPPING_classifiers">
<Mapping_Classifiers>
<xsl:for-each select="$tokenize_classifiers">
<xsl:variable name="tokenize_further" select="tokenize(.,':')"/>
<xsl:variable name="index"><xsl:value-of select="index-of($tokenize_classifiers,.)" /></xsl:variable>
  <xsl:element name="classifier">
    <xsl:attribute name="index">
      <xsl:value-of select="$index" />
    </xsl:attribute>
    <xsl:for-each select="$tokenize_further">
      <xsl:element name="class">
        <xsl:value-of select="." />
      </xsl:element>
    </xsl:for-each>
  </xsl:element>
</xsl:for-each>
</Mapping_Classifiers>
</xsl:variable>

as:

<xsl:variable name="MAPPING_classifiers" as="element()*">
<xsl:for-each select="$tokenize_classifiers">
  <classifier index="{position()}">
    <xsl:for-each select="tokenize(.,':')">
      <class>
        <xsl:value-of select="."/>
      </class>
    </xsl:for-each>
  </classifier>
</xsl:for-each>
</xsl:variable>

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old May 30th, 2007, 03:31 PM
Authorized User
 
Join Date: May 2007
Posts: 79
Thanks: 0
Thanked 0 Times in 0 Posts
Default

If my current context is the row for input1:

<xsl:template match="row">

Would the expression then change to:

<xsl:variable name="this" select="current()"/>
<xsl:variable name="match" select="$doc2//row[
   some $r in $this satisfies
     every $c in $MAPPING_classifiers/classifier satisfies
      (./cell[@name=$c/class[2]] and $r/cell[@name=$c/class[1]])]"/>

For some reason, it is picking up every row in input2. I assume I am missing something.

Thanks again.
 
Old May 30th, 2007, 03:58 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

There's nothing in my expression that depends on the context node. But of course it may be wrong - I'm leaving you to debug it! Certainly changing "some $r in $doc1//row" to "some $r in $this" is nonsense - you never need to say "some $r in $this" when $this is a singleton. But perhaps you're trying to solve a different problem instead of finding all the rows in doc2 that match some row in doc1, you're looking for the rows in doc2 that match a specific row in doc1? In that case you don't need "some $r in $doc1//row satisfies" at all, you just need to replace $r with current().

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
select nodeset newbies1234 XSLT 4 August 22nd, 2008 10:52 AM
convert nodeset to a single node newbies1234 XSLT 2 August 18th, 2008 10:01 AM
Reversing nodeset sudhish.sikhamani XSLT 3 June 19th, 2008 11:43 AM
with-param nodeset RoeZ XSLT 6 November 1st, 2007 06:53 PM
Nodeset as Parameter... venutm XSLT 6 February 24th, 2006 03:07 PM





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