Xpath Value based on Child Node - xslt

From the below xml,i need an xpath to take the id value only when the state is FL.
Please help
<Employee_Details>
<Payroll>
<id>A1</id>
<City>Dallas</City>
<State>TX</State>
</Payroll>
<Payroll>
<id>A2</id>
<City>Orlando</City>
<State>FL</State>
</Payroll>

"i need an xpath to take the id value only when the state is FL"
That can be translated into the following XPath expression :
/Employee_Details/Payroll[State='FL']/id
maybe you want to append /text() at the end to return the text node inside <id> element instead of the element itself.

Related

How to get the value of the parent element from the current element in XSLT?

How to get parent node value using XSLT and XPath, for below xml response : <cartridge name="Standard Grid Wall" type="StandardGridWall"> , I want to get value of type . Please help
Apparently, my comment helped, so here it is, posting it as answer:
How to get the value of the parent node? Use:
<xsl:value-of select="parent::node()" />

XPath - Proper syntax for retrieving attributes

I feel like I'm derping hard here, but I can I find the value of attribute2, based on attribute 1?
Take
<node attribute1="a" attribute2="b">Some Stuff</node>
I've tried this
//node[#attribute1=a]#content
with no success.
Thanks
You can use the XPath:
//node[#attribute1="a"]/#attribute2
This says to:
Find the node that has an attribute1 value of "a"
For the node found, return its attribute2 value

XSLT - Key() function

I'm a bit confused about this key function:
<xsl:for-each select="article[count(. | key('idkey', #id)[1]) = 1]>
Is there anyone that can briefly explain whats happening in this for-each loop?
The key is: <xsl:key name="idkey" match="/newspapers/newspaper" use="#id"/>
#id is an attribute in newspaper.
Thanks.
The expression key('idkey', #id)[1] selects the first element whose idkey is equal to #id.
The expression count(A|B) = 1 is an insane XSLT 1.0 workaround for testing whether A and B are the same node. (You will also see people using generate-id(A)=generate-id(B) for this.)
Put these together and you are asking whether the current element is the first one in the document that has a particular id value.
This is the basis of the technique called Muenchian Grouping (which becomes redundant in XSLT 2.0).
There is something fishy about the code because the key seems to be matching newspaper id's, not article id's. But perhaps they are related in some way.
In this for-each element
<xsl:for-each select="article[count(. | key('idkey', #id)[1]) = 1]">
The for-each is being applied to the first article element for each #id attribute.
The call key('idkey', #id) is selecting all article elements with the same #id attribute as the current one.
key('idkey', #id)[1] selects the first of all article elements with the same #id.
Because a node cannot appear in a node set more than once, the union . | key('idkey', #id)[1] will contain one node if the current article is the same node as the first article with the same #id. Otherwise it will contain two.
Checking that the value of count() is one selects only the elements that are the first with any #id.
An alternative way of doing this, and the one I prefer, is to use generate-id like this
select="article[generate-id() = generate-id(key('idkey', #id)[1])]"
which checks directly whether the current element is the same one as the first element in the set by comparing their generated IDs.

How can I use xsl stylesheet parameters to set a node name in XPATH expression?

I have the following XPATH expression:
select="catalog/product/$category_name = $category_value"
In the given example $category_name and $category_value are the XSL parameters that I receive from my servlet and I want to use them in XSL to filter the XML result based on category and its value.However, for some reason when,say, $category_name parameter equals 'price' attribute of the 'product' parent node and $category_value equals 40, the given expression does not return any result at all! Logically, the expression should be transformed to something like select="catalog/product/price = 40"....I guess there is some problem with specifying the node name which is the category in my case. Can anyone suggest the way to get around this problem?
You probably want:
catalog/product/*[name()=$category_name] [. = $category_value]
For variable xpath expressions, use dynamic xpath. See Is it possible to use a Dynamic xPath expression in a xslt style sheet?

XSLT: attribute value used as numeric predicate

Given
<xsl:variable name="datePrecision" as="element()*">
<p>Year</p>
<p>Month</p>
<p>Day</p>
<p>Time</p>
<p>Timestamp</p>
</xsl:variable>
The expression
$datePrecision[5]
returns a nodeSet containing one text node with value "Timestamp", as expected.
Later in a template, with a context element having an attribute
#precision="5"
I try the following expressions but all return an empty string:
$datePrecision[#precision]
$datePrecision[number(#precision)]
$datePrecision[xs:decimal(#precision)]
However, the following sequence does what I want
<xsl:variable name="prec" select="number(#precision)"/>
... $datePrecision[$prec] ...
Using Oxygen/XML's debugger I've stepped to the point where the expression is about to be evaluated and display the following in the watch window:
Expression Value Nodes/Values Set
-------------------------- --------------- -----------------------
$datePrecision[5] Node Set(1) #text Timestamp
#precision Node Set(1) precision 5
$datePrecision[#precision]
number(#precision) 5
$datePrecision[number(#precision)]
$prec 5
$datePrecision[$prec] Node Set(1) #text Timestamp
Obviously I've missed something fundamental about how attribute nodes are atomized for use in a predicate, but can't find anything in the docs (Michael Kay's XSLT/XPATH 2.0, 4th ed) that would explain this difference.
Can someone explain why this is occurring, and point me to where, in either the XSLT 2.0 spec or Michael Kay's book, where this is described?
(the XSLT processor is Saxon-PE 9.2.0.3)
Obviously I've missed something
fundamental
Yes. The XPath expression:
$datePrecision[#precision]
means: all elements in $datePrecision that have an attribute named precision.
But you want #precision to mean the attribute named precision of the currnet node that is matched by the template.
XSLT provides the current() function exactly for this purpose. Use:
$datePrecision[current()/#precision]
UPDATE: As Martin Honnen hinted, the OP probably wants to get the 5th element out of $datePrecision -- something not immediately visible from the description of the problem. In this case, it may be necessary to use:
$datePrecision[position() = current()/#precision]