Jump to content

How to reference one element from another anywhere


javajoemorgan

Recommended Posts

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

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

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

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
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).
Link to comment
Share on other sites

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

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...