Re: [xsl] Selecting the value from diff i/p XML

Subject: Re: [xsl] Selecting the value from diff i/p XML
From: Mukul Gandhi <gandhi.mukul@xxxxxxxxx>
Date: Fri, 17 Sep 2010 09:29:11 +0530
Hi Shashank,
     Here's some more analysis from my point of view about use of XSL key's.

1. If we read the definition of keys in XSLT (2.0) spec (ref,
http://www.w3.org/TR/xslt20/#key) it says:

<quote>
Keys provide a way to work with documents that contain an implicit
cross-reference structure. They make it easier to locate the nodes
within a document that have a given value for a given attribute or
child element, and they provide a hint to the implementation that
certain access paths in the document need to be efficient.
</quote>

Therefore usage of XSL key's would generally make access to XDM nodes
faster, if the XML document size is large and the XSLT stylesheet
tries to do multiple invocations to the "key" function. Multiple
invocations (and if too many if we want to look at the trade-off
between document size vs no of key accesses) of key's really realize
the benefits of keys, because then the stylesheet is trying to make
vast traversals of XDM nodes (and not necessarily in linear fashion
in-memory).

2. The XSLT 2.0 definition of keys is following:

<xsl:key
  name = qname
  match = pattern
  use? = expression
  collation? = uri>
  <!-- Content: sequence-constructor -->
</xsl:key>

and the correspoding "key" functions:

    2.1 key($key-name as xs:string, $key-value as xs:anyAtomicType*) as
node()*

    2.2 key($key-name 	 as xs:string,
                $key-value	         as xs:anyAtomicType*,
                $top 	                 as node()) as node()*

whereas for 1.0 it is following:

<xsl:key
  name = qname
  match = pattern
  use = expression />

and the corresponding "key" function is:

node-set key(string, object)

As we could see that in 2.0, the key-value for a particular "key"
invocation can also be provided by a sequence constructor, which makes
the 2.0 construct quite useful than 1.0 (where this isn't available).
The key-value in 2.0 is much strongly typed (ref, xs:anyAtomicType*)
-- "so we can target the key look-ups for particular types of atomic
values (of cardinality *)", than corresponding one in 1.0.

In your example, if the document size is not too large and you don't
do multiple invocations of "key" function, I believe you may still go
for the non-key solution. This is a trade-off you need to make, for
your particular use-case.

On Fri, Sep 17, 2010 at 2:58 AM, Shashank Jain <shashankjain@xxxxxxxx> wrote:
>
> Thanks Gerrit for the new solution.
>
> Yea I messed the xsl:key declaration. Thanks for pointing out.
>
> Now there is slight change, earlier I was printing values only of those ID's
which were in root1.xml.
> But now I want to look for the values of for root 2.xml after comparing
their id's from root1.xml.
> For better understanding I am giving my i/p xml's again.
>
> ===================Root1.xml========================
> <root1>
> B B B  B B B  <item id="1" value="A"/>
> B B B  B B B  <item id="2" value="B"/>
> B B B  B B B  <item id="3" value="C"/>
> B B B  B B B  <item id="4" value="D"/>
> B B B  B B B  <item id="5" value="E"/>
> B B B  B B B  <item id="6" value="F"/>
> B B B  B B B  <item id="7" value="G"/>
> B B B  B B B  <item id="8" value="H"/>
> B B B  B B B  <item id="9" value="I"/>
> B B B  B B B  <item id="10" value="J"/>
> </root1>
>
> ===================Root2.xml========================
> <root2>
> B B B  <data id="2"/>
> B B B  <data id="2"/>
> B B B  <data id="3"/>
> B B B  <data id="1"/>
> B B B  <data id="5"/>
> B B B  <data id="5"/>
> B B B  <data id="7"/>
> B B B  <data id="8"/>
> B B B  <data id="4"/>
> B B B  <data id="1"/>
> B B B  <data id="1"/>
> B B B  <data id="2"/>
> </root2>
> ==================Output==================
> 2=B
> 2=B
> 3=C
> 1=A
> 5=E
> 5=E
> 7=G
> 8=H
> 4=D
> 1=A
> 1=A
> 2=B
>
> ================XSLT======================
> B <xsl:key name="idlist" match="root2/data" use="@id"/>
> B <xsl:variable name="data" select="document('Root1.xml')"
as="document-node(element(root1))"/>
> B B  <xsl:template match="/">
> B B B B  <wrapper>
> B B  B B B  <xsl:apply-templates select="root2/data"/>
> B B B B  </wrapper>
> B B  </xsl:template>
> B B  <xsl:template match="data">
> B B B B  <out>
> B B B  B B B  <xsl:if test="$data/root1/item[@id=current()/@id]">
> B B B  B B B  B B B  <xsl:value-of select="@id"/>
> B B B  B B B  B B B  <xsl:text>=</xsl:text>
> B B B  B B B  B B B  <xsl:value-of
select="$data/root1/item[@id=current()/@id]/@value"/>
> B B B  B B B  B B B  <br/>
> B B B B  B B B  </xsl:if>
> B B B  B  </out>
> B B  </xsl:template>
>
> I am able to get the desired output by using above code but it lacks
efficiency.
> How to use the key function to get the desired output.
>
> Shashank



--
Regards,
Mukul Gandhi

Current Thread