472,805 Members | 1,757 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,805 software developers and data experts.

XPath using an element value in XSL

Hi,

I have some XML like this:

<family>
<person name="bob">
<father ref="../../person[2]" />
</person>
<person name="charlie">
<child ref="../../person" />
</person>
</family>

When I template match on person I want to get a handle on the referenced
father element so that I can apply a template to it. Does anyone know if
this is possible and how?

E.g.
<xsl:template match="person">
<xsl:value-of select="@name"/>
<xsl:if test="count(father) != 0">
Father: <xsl:apply-templates select="eval(@ref)">
</xsl:if>
</xsl:template>

Note that the eval() function is what I'm missing.

Many thanks
Pat Turner
Jul 20 '05 #1
4 3383
Note that the eval() function is what I'm missing.


it is provided as an extension function by some systems (eg saxon has a
saxon:evaluate that does this)

the pure XSLT1 way of doing this is a two stage transform, in the first
pass you write out a stylesheet that has the XPath extracted from the
source in a suitable select attribute, then you execute the generated
stylesheet.

David
Jul 20 '05 #2
Thanks David,

errrm, could you give me an example of what the first pass stylesheet
would look like using my example? I can't think how it would be done.

TIA
Pat
David Carlisle wrote:
Note that the eval() function is what I'm missing.

it is provided as an extension function by some systems (eg saxon has a
saxon:evaluate that does this)

the pure XSLT1 way of doing this is a two stage transform, in the first
pass you write out a stylesheet that has the XPath extracted from the
source in a suitable select attribute, then you execute the generated
stylesheet.

David

Jul 20 '05 #3
Pat Turner <pu************@netscape.net> writes:
Thanks David,

errrm, could you give me an example of what the first pass stylesheet
would look like using my example? I can't think how it would be done.

TIA
Pat


several ways, depending how generic/efficient you want to be.

for example

input doc (eval.xml):

<family>
<person name="bob">
<father ref="../../person[2]" />
</person>
<person name="charlie">
<child ref="../../person[1]" />
</person>
</family>
proto-stylesheet (eval1.xsl)
<xsl:stylesheet version="1.0"
xmlns:x="data:,x"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>

<xsl:template x:match="father">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

<xsl:template x:match="child">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

</xsl:stylesheet>
in the above the syntax (which I just made up) is that templates
depending on a generated xpath use x:match in their match pattern, and
use x:select where they want the xpath to appear. This could be made
more efficient (i generate all templates for all dynamic xpaths which is
less code for me to write but generates more templates than needed)

Evaluation stylesheet (this has original source doc filename hardcoded,
it could be a parameter)

<xsl:stylesheet version="1.0"
xmlns:x="data:,x"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>

<xsl:template x:match="father">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

<xsl:template x:match="child">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

</xsl:stylesheet>



generate real stylesheet
saxon -o eval2.xsl eval1.xsl eval.xsl

eval2.xsl has several templates expanded out. and looks like

<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="data:,x" version="1.0">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>
<xsl:template match="father[@ref='../../person[2]']">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[2]"/>
</xsl:template>
<xsl:template match="father[@ref='../../person[1]']">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[1]"/>
</xsl:template>
<xsl:template match="child[@ref='../../person[2]']">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[2]"/>
</xsl:template>
<xsl:template match="child[@ref='../../person[1]']">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[1]"/>
</xsl:template>

</xsl:stylesheet>

run this stylesheet on original source:

$ saxon eval.xml eval2.xsl
<?xml version="1.0" encoding="utf-8"?>

Person: bob
Father: charlie

Person: charlie
Child: bob

Jul 20 '05 #4
Hi David,

thanks very much for the thorough working example. I see what you have
done. I guess if I wanted a generic way to provide this functionality
I'd have to write a third pass stylesheet. I.e. if I have no way of
knowing which nested elements are references of not.

FYI, I'm actually transforming a serialised graph of Java objects. This
means that elements which use references and elements which don't can
change quite easily when java code is refactored. So a generic, reusable
solution would be more pleasing.

I think it also shows that I'll be much better off using an extension. I
believe Xalan (which I am using) has such an evaluate function.

I appreciate knowing how it can be done nonetheless.

Thanks again,
Pat.

David Carlisle wrote:
Pat Turner <pu************@netscape.net> writes:

Thanks David,

errrm, could you give me an example of what the first pass stylesheet
would look like using my example? I can't think how it would be done.

TIA
Pat

several ways, depending how generic/efficient you want to be.

for example

input doc (eval.xml):

<family>
<person name="bob">
<father ref="../../person[2]" />
</person>
<person name="charlie">
<child ref="../../person[1]" />
</person>
</family>
proto-stylesheet (eval1.xsl)
<xsl:stylesheet version="1.0"
xmlns:x="data:,x"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>

<xsl:template x:match="father">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

<xsl:template x:match="child">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

</xsl:stylesheet>
in the above the syntax (which I just made up) is that templates
depending on a generated xpath use x:match in their match pattern, and
use x:select where they want the xpath to appear. This could be made
more efficient (i generate all templates for all dynamic xpaths which is
less code for me to write but generates more templates than needed)

Evaluation stylesheet (this has original source doc filename hardcoded,
it could be a parameter)

<xsl:stylesheet version="1.0"
xmlns:x="data:,x"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>

<xsl:template x:match="father">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

<xsl:template x:match="child">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" x:select="@ref"/>
</xsl:template>

</xsl:stylesheet>



generate real stylesheet
saxon -o eval2.xsl eval1.xsl eval.xsl

eval2.xsl has several templates expanded out. and looks like

<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="data:,x" version="1.0">
<xsl:template mode="a" match="person">
<xsl:value-of select="@name"/>
</xsl:template>

<xsl:template match="person">
Person: <xsl:value-of select="@name"/>
<xsl:apply-templates select="father|child"/>
</xsl:template>
<xsl:template match="father[@ref='../../person[2]']">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[2]"/>
</xsl:template>
<xsl:template match="father[@ref='../../person[1]']">
Father: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[1]"/>
</xsl:template>
<xsl:template match="child[@ref='../../person[2]']">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[2]"/>
</xsl:template>
<xsl:template match="child[@ref='../../person[1]']">
Child: <xsl:value-of select="@name"/>
<xsl:apply-templates mode="a" select="../../person[1]"/>
</xsl:template>

</xsl:stylesheet>

run this stylesheet on original source:

$ saxon eval.xml eval2.xsl
<?xml version="1.0" encoding="utf-8"?>

Person: bob
Father: charlie

Person: charlie
Child: bob


Jul 20 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: worli | last post by:
Hi All, I have a strange requirement. I have a dynamic input numeric data stream e.g. 2, 2, 4, 5 etc.... ( each input number range from 1 to 10 ). lets take a simple case where all inputs will...
4
by: David Dvali | last post by:
Hello. I have such XML file: <root> <elem1> <optional> Some data <optional> </elem1> </root>
2
by: Rich | last post by:
I am very new to ASP.NET, and did not see a similar error posted anywhere. Here is my situation. I followed the instructions in Peter Bromberg's excellent article "Host Winforms - based...
1
by: Filip Hendrickx | last post by:
Hi there. I want to generate elements, choosing the element name dynamically. So I tried to use attribute value templates: <xsl:element name="{$local-name($someNode)}"> <!-- Generate element...
6
by: luthriaajay | last post by:
How can I get the value of a particular element in the flwg XML using Java? Value of Document newSingleOrderDocument is: <?xml version="1.0" encoding="UTF-8"?> <FIXML...
2
by: luthriaajay | last post by:
I need some help to extract the LatestFillQuantity element value using XPATH. in Java. I am unable to extract the value of 10000. Please help as to what have I done wrong.? Help appreciated. ...
1
by: luthriaajay | last post by:
Using <xsl:value-of in XSL XML file <i:Details> <i:Stra> <stra:Desc>ABC</stra.Desc>
3
by: RhazeMondragon | last post by:
hello!!! i encounter problem by searching the records the database by using date value what would be the appropriate sql command that would fit in this problem.... thanks a lot!!!
3
by: thomas | last post by:
I want to use a priority_queue like STL data structure. But I found that priority_queue cannot update element value: only pop/ push is supported. I'm using priority_queue to implement the prim...
2
by: MATTXtwo | last post by:
I want to get input element value in a form not using Javascritp like: var NICNo=document.getElementById("NewICNo").value;
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.