javajoemorgan Posted January 18, 2008 Share Posted January 18, 2008 I have an XML where there are internal references to other elements. IDs are used as those references. These elements can exist anywhere in the tree, either by forward or reverse reference, and at any level. When I encounter a reference element, I get it's REFID attribute, and then look for the referenced element having that ID. Here is a very simple example of the XML: <X> <A> <TARGET ID="xxxx"/> <B> <TARGET ID="yyyy"/> <REF REFID="123"/> </B> <TARGET ID="zzzz"/> </A> <D> <TARGET ID="123"/> </D> <TARGET ID="aaaa"/></X> As you see, the REF element refers to the TARGET having the ID="123". That seems easy enough with something like://TARGET[@ID=@REFID]However, I don't exactly know how to format the call, since "@ID=@REFID" doesn't work. I understand why, I just don't know how to make the comparison.In addition, I need to be able to compute the numerical "instance" of the TARGET element within the entire document, not just it's position. So, with reference to the above example, I will need to be able to resolve that the TARGET element with ID="123" is the 4th TARGET element in the document."Java" Joe Morgan Link to comment Share on other sites More sharing options...
boen_robot Posted January 18, 2008 Share Posted January 18, 2008 There's the xsl:key element, and the key() function, but honestly said, I'm not completely sure how they work yet.Another way you could try is with the current() function. To be more precise, if you're casting the expression while your current context is the REF element, you could have //TARGET[@ID=current()/@REFID] Link to comment Share on other sites More sharing options...
javajoemorgan Posted January 18, 2008 Author Share Posted January 18, 2008 There's the xsl:key element, and the key() function, but honestly said, I'm not completely sure how they work yet.Another way you could try is with the current() function. To be more precise, if you're casting the expression while your current context is the REF element, you could have//TARGET[@ID=current()/@REFID] Oh boy... thanks a million... it was the key() I started with but couldn't figure it out either, so wanted to go the other way, and didn't know how to do the "current()/@REFID" part.... However, being the hard-headed kind I am, I revisited my key issue, and got it to work. Now I'm wondering which one is faster? My XML docs are potentially very large, so I would suspect that using key would be faster. "Java" Joe Morgan Link to comment Share on other sites More sharing options...
boen_robot Posted January 18, 2008 Share Posted January 18, 2008 Oh boy... thanks a million... it was the key() I started with but couldn't figure it out either, so wanted to go the other way, and didn't know how to do the "current()/@REFID" part.... However, being the hard-headed kind I am, I revisited my key issue, and got it to work. Now I'm wondering which one is faster? My XML docs are potentially very large, so I would suspect that using key would be faster. "Java" Joe MorganJust curious... given the XML and the XPath expression above, what's the equivalent code with key() (including the use of the xsl:key element). Link to comment Share on other sites More sharing options...
javajoemorgan Posted January 18, 2008 Author Share Posted January 18, 2008 Just curious... given the XML and the XPath expression above, what's the equivalent code with key() (including the use of the xsl:key element). <!-- before the first template --><xsl:key name="targets" match="TARGET" use="@ID"/><!-- In the template where you need it --><xsl:for-each select="key('targets', string(@REFID))">...</xsl:for-each> For me, it was the "string(@REFID)" I had to figure out... and how your "current()/@REFID" made me think of it... I don't know.... but whatever wierd paths my axons and dendrites run... sometimes I'm thankful for! "Java" Joe Morgan Link to comment Share on other sites More sharing options...
aalbetski Posted January 18, 2008 Share Posted January 18, 2008 The following shows the use of the key()1. <xsl:key> establishes what we are looking for and how to find it. We are looking for TARGET nodes (match) and we will find them using the ID Attribute (use). We give it a name so that the processor can use it later. We could have several setup2. We get the value of the REFID (123) during the for-next and pass that value to the key() funtion. It says use the key we set up with the name TargetId and look through all the TARGET nodes for one (or more) with an ID Attrtibute that has this value. Then return the ID attribute of the one found. We could have returned anything and I illustrate this with the second key() returning the node nameHope this clears it up a litlleBTW, your first item failed (//TARGET[@ID=@REFID]) because TARGET does not have a REFID attribute. You could have gotten it to work by first assigning @REFID to a variable and then do the comparison <xsl:variable name="refid" select="@REFID"/>//TARGET[@ID=$refid] <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:key name="TargetId" use="@ID" match="TARGET" /> <xsl:template match="*"> <xsl:for-each select="//REF"> <xsl:value-of select="key('TargetId',@REFID)/@ID"/> <xsl:value-of select="name(key('TargetId',@REFID))"/> </xsl:for-each> </xsl:template></xsl:stylesheet> Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.