XSLT 1.0 Index of node or sibling no - xslt

Maybe a noob question, but here goes...
I need to extract the index number of a node that is deep within an xml.
Let's say I'd like to find the index (wich of the int-nodes) that has the value 3 in the following XML:
<Result>
<races>
<int>2</int>
<int>3</int>
<int>4</int>
<int>5</int>
<int>6</int>
</races>
</Result>
Anyone got a simple solution for this?
Best regards,
Sam

I am not sure I fully understand your question. From the context of the / root node:
<xsl:value-of select="count(Result/races/int[.='3']/preceding-sibling::int)" />
will return the 0-based index number of the specified int node (1 in the given example).

Related

pre-processing script to switch product codes

I have a snippet of code I've inherited and I'm trying to get it to work on multiples of the match pattern and set a tag from looking up a value from a table using another tag. What happens is that, for every item, the same lookup is performed and not the relative one for the node. I can't work out the syntax to work thru all entries and substitute the correct one. It's got to be simple it's just that I am simpler :)
My source xml contains this (within an outer /oomsdoc document node not shown):
<item>
<lineqty> 1</lineqty>
<linesku>BNLP5008 </linesku>
<linecustprod>xxxxxxxxxxxxxxx</linecustprod>
<linedesc>London Pride (Bot500mlx8) </linedesc>
</item>
<item>
<lineqty> 1</lineqty>
<linesku>BNBL5008 </linesku>
<linecustprod>xxxxxxxxxxxxxxx</linecustprod>
<linedesc>Bengal Lancer (Bot500mlx8) </linedesc>
</item>
I want to substitute the xxxxxxxxxxxxxxx in each linecustprod tag with the material from the lookup table using the value of the linesku tag.
This is my lookup table:
<Materials>
<product sku='BNLP5008 ' material='LONDON PRIDE'/>
<product sku='BNBL5008 ' material='BENGAL LANCER'/>
</Materials>
and this is my xslt code.
<xsl:variable name="SkuList" select="document('d:\test\transforms\catalogue.xml')/Materials"/>
<xsl:template match="/oomsdoc/item/linecustprod">
<xsl:variable name="MySku" select="/oomsdoc/item/linesku"/>
<linecustprod>
<xsl:value-of select="$SkuList/product[#sku=$MySku]/#material"/>
</linecustprod>
</xsl:template>
I'm guessing some kind of xsl foreach would work but just can't find a usable example to crib :)
Your guidance again would be appreciated at this point in my frustration :)
Thanks,
Brian.
Changing the variable definition to
<xsl:variable name="MySku" select="../linesku"/>
should be sufficient, this will pull out the linesku that is a sibling to the linecustprod you're currently looking at. As currently defined the variable will contain a node set of all the linesku elements in the document, so the value-of will give you the first entry from $SkuList that matches any entry in the main input file.
In addition to Ian Roberts' answer, please change
<xsl:variable name="SkuList" select="document('d:\test\transforms\catalogue.xml')/Materials"/>
to
<xsl:variable name="SkuList" select="document('/d:\test\transforms\catalogue.xml')/Materials"/>
for some reason, the first throws an error (malformed URL).

xsl - select node by child

I have a problem selecting just elements of an xml, which contain a specific child node. Asumme the following part of an xml:
<root>
<Navision.Buchungen>
<Saldo>-110867.7500</Saldo>
<Navision.Kontostruktur>
<Bereich>1</Bereich>
</Navision.Kontostruktur>
</Navision.Buchungen>
<Navision.Buchungen>
<Saldo>-3082585.2100</Saldo>
<Navision.Kontostruktur>
<Bereich>2</Bereich>
</Navision.Kontostruktur>
</Navision.Buchungen>
...
</root>
Now I have an xsl part like this to get the sum of 'Saldo':
<xsl:variable name="FACT0" select="sum(//root/Navision.Buchungen/Saldo)"/>
But how can I select just the Saldo for 'Bereich' 1 for example?
Use this XPath:
//root/Navision.Buchungen[Navision.Kontostruktur/Bereich = 1]/Saldo
//root/Navision.Buchungen[Navision.Kontostruktur/Bereich = 1]/Saldo
Edited:
oh already posted.
For further problems you can use one of the online testbeds like this one. And of course good manuals like those from w3schools, also with testbeds for xsl

Question on XSLT following-sibling

My XML structure looks like this
<COMPANY>
<COMPANY-DATA>ABC</COMPANY-DATA>
<ID>10800</ISSUE-ID>
<PROJECT-ID/>
</COMPANY-ISSUE-INFO>
</COMPANY>
"COMPANY Node repeats"
What I want to do is I want to do I want to check for COMPANY-DATA='ABC' and get its ID
I tried using
<xsl:value-of select="//COMPANY-DATA/.='ABC'/following-sibling::ID/."/>
But this doesn't seem to work and throwing error
Expression must evaluate to node-set
//COMPANY-DATA/.= -->'ABC'<--
/following-sibling::ID/.
Thanks,
Karthik
Edit: I found the solution
**<xsl:value-of select="//COMPANY-DATA[.='ABC']/following-sibling::ID/."/>**
Thanks
The first thing i noticed ist, that whe snipped you postet is no valid XML. The Element <ID> is closed by the End-Element </ISSUED_ID> and there is a single closing Element </COMPANY-ISSUE-INFO>
But if i get you right, you want to find the ID of the <COMPANY> Element where the <COMPANY-DATA> is ABC. So your Comment on your question should do this. But you could also use
<xsl:value-of select="//COMPANY[COMPANY-DATA='ABC']/ID"/>
This removes the need of having the Comapny-Data and ID in a specific sequence.
<xsl:value-of select="//COMPANY-DATA[.='ABC']/following-sibling::ID/."/>

Using dynamic xpath in XSLT

I am using a variable say xpathvar in the XSLT whose value will be supplied at the time of call to XSLT. How can i achieve this?
My XSLT file looks like -
<xsl:param name="xpathvar"/>
<xsl:param name="keyxpath"/>
<xsl:template match="/">
<listofResults>
<xsl:for-each select="$xpathvar">
<keyvalues><xsl:value-of select="xalan:evaluate(substring-before($keyxpath,'||'))"/></keyvalues>
<keyvalues><xsl:value-of select="xalan:evaluate(substring-after($keyxpath,'||'))"/></keyvalues>
</xsl:for-each>
</listofResults>
</xsl:template>
</xsl:stylesheet>
If I mention the variable in the for-each, it throws error. Please guide how can I achieve this.
Thanks!
According to Global xsl:param containing xpath expression string it can't be done purely with plain old XSLT, you need to use the evaluate extension see: Xalan evaluate expression
I dont think this can be done like this you must use xpath so example would be
<template match="Node[name=$xpathvar]" />
<xsl:for-each select="*[name()=$xpathvar]">
</xsl:for-each>
I think it does not let you use the variable directly because it is not a nodeset.
If I mention the variable in the
for-each, it throws error
In XSLT 1.0 (it looks you are using Xalan), you can iterate over node sets, only. So $xpathvar should be an instance of node set data type.
In XSLT 2.0 you can iterate over sequence (including scalar values).
Also, if the string containing the "dynamic" XPath expression is simple enough (only QName test step, maybe positional predicates) this could be done (as is already answered in SO) with standar XSLT.

Determining whether a node is contained within another node in XSLT

Is it possible to tell whether a node is contained within (or equal to) another node in XSLT? For example, consider this code snippet:
<xsl:variable name="itemSection" select=".."/>
<xsl:for-each select="key('enemyItems', #key)">
<xsl:variable name="enemyList" select="./attributes/#value"/>
<xsl:variable name="enemyListSection" select="../../.."/>
.
.
.
</xsl:for-each>
Is it possible to tell whether itemSection is contained within (or equal to) enemyListSection?
In XPath 1.0
$itemSection[ancestor::*[generate-id()=generate-id($enemyListSection)]]
In XPath 2.0
$itemSection[ancestor::*[. is $enemyListSection]]
Just a small adjustment to Alejandro's answer:
In XPath 1.0
$itemSection[ancestor-or-self::*[generate-id()=generate-id($enemyListSection)]]
In XPath 2.0
$itemSection[ancestor-or-self::*[. is $enemyListSection]]
Because the original question asked:
Is it possible to tell whether
itemSection is contained within (or
equal to) enemyListSection?