2

In my xsl, I want to match on several nodes and then grab the value of the matched node into a variable. How can I do that?

I need to place a wildcard variable in place of Budget0 below:

<xsl:template match="FieldRef[@Name='Budget0' or @Name='Scope' or @Name='Risk' or @Name='Schedule']" mode="body">
    <xsl:param name="thisNode" select="."/>
    <xsl:variable name="currentValue" select="$thisNode/Budget0" />
    <xsl:variable name="statusRating1">(1)</xsl:variable>
    <xsl:variable name="statusRating2">(2)</xsl:variable>
    <xsl:variable name="statusRating3">(3)</xsl:variable>

    <xsl:choose>
        <xsl:when test="contains($currentValue, $statusRating1)">
            <span class="statusRatingX statusRating1"></span>
        </xsl:when>
        <xsl:when test="contains($currentValue, $statusRating2)">
            <span class="statusRatingX statusRating2"></span>
        </xsl:when> 
        <xsl:when test="contains($currentValue, $statusRating3)">
            <span class="statusRatingX statusRating3"></span>
        </xsl:when> 
        <xsl:otherwise>
            <span class="statusRatingN"><xsl:value-of select="$currentValue" /></span>
        </xsl:otherwise>                    
    </xsl:choose>
</xsl:template> 

In this snippet, the xsl:template match... works just fine; it does seem to match those fields. I can see in Firebug that those fields receive the statusRating1 css class just like they should (since they are all set to receive the value of the Budget0 field.

[update]

I found that if I use this for the variable:

<xsl:variable name="currentValue" select="current()/@Name" />

or

<xsl:variable name="currentValue" select="FieldRef[@Name=current()/@Name"] />

It will get caught in the otherwise tag, and will print the name of the field. In other words, the html prints

<span class="statusRatingN">Budget0</span>

If I try any of Dimitre's solutions (below), it never matches in any of the when clauses, and the html is outputted like this (notice the span's text is blank):

<span class="statusRatingN"></span>

Therefore, I deduce that the $currentValue is only getting the name of the attribute, it isn't referring to value of the node. I need to refer to the value of that particular node.

Flynn1179
  • 11,925
  • 6
  • 38
  • 74
bgmCoder
  • 6,205
  • 8
  • 58
  • 105

2 Answers2

1

Use:

<xsl:variable name="currentValue" select="$thisNode/*[name()=current()/@Name]"/>

Or, alternatively:

<xsl:variable name="currentValue" select="$thisNode/*[name()=$thisNode/@Name]"/>

Or, alternatively (best):

<xsl:variable name="currentValue" select="*[name()=current()/@Name]"/>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • Are you sure? that seems to only load the value of the first matched element name. – bgmCoder Dec 27 '12 at 17:56
  • Maybe the `match` method would have to be adjusted to use this? – bgmCoder Dec 27 '12 at 17:56
  • @BGM, Yes I am sure. Why just don't you try this? It isn't the "first matched element name" -- it is all elements, whose name is the string value of the `Name` attribute` of the current node. – Dimitre Novatchev Dec 27 '12 at 18:05
  • I did try it - it seems to have the same effect as if I had only made a `match` on the first `fieldref` name. I've restarted the website portal about 5 times all to no effect. This xsl stuff is complicated to me. – bgmCoder Dec 27 '12 at 18:07
  • @BGM, I corrected the answer -- there was an error in using the context. – Dimitre Novatchev Dec 27 '12 at 18:07
  • Thanks, Dimitre. I tried that too, but it doesn't do it. Even with your edit, it still seems to read the value of the first match. Maybe the problem has to do with the 'match` method? – bgmCoder Dec 27 '12 at 18:09
  • Okay, I've tried all three now (you got my vote). I think I actually understand what we are doing. However, none of these are getting the cigar... – bgmCoder Dec 27 '12 at 18:12
  • @BGM, There is no such thing as "the first match". There is only one, single attribute `Name` and it has a single value. We select the child of the current node, whose name is the string value of the `Name` attribute of the current node. If the `Name` attribute has value "Budget0" then the child named `Budget0` is selected. If the `Name` attribute has value `"Scope"`, then the child named `Scope` is selected, ..., etc., ... Or do you want something else to be done? – Dimitre Novatchev Dec 27 '12 at 18:13
  • No, what I am saying is that it never matches. It always applies the `otherwise` - no matter which of the three solutions you propose. `$currentValue` seems to always be blank. If I use the fieldref name instead of the "wildcard" then it will match that one just fine, but these snippets don't allow for a match. – bgmCoder Dec 27 '12 at 19:22
  • @BGM, I haven't seen your XML. How could I know what you want to select??? Do you want to select elements by name, or do you want to select `FieldRef` elements by the value of their `Name` attribute? Please, *edit* the question and add the missing important data. – Dimitre Novatchev Dec 27 '12 at 19:30
  • We were on the right track, I think (it is Sharepoint, and I can't seem to get the xml, I tried what you proposed to me in another post but to no avail, and you never responded to me in the chat to try and get any further). There isn't any missing data in the question. I am trying to match the @name of the fieldref we have matched. These solutions you suggest do not grab that value. I can see the outputted html, and `$currentValue` is always blank. The `match` works perfectly, however. Can we not get the `value` of the currently matched field? – bgmCoder Dec 27 '12 at 19:37
  • @BGM, What do you mean by "the matched field"? – Dimitre Novatchev Dec 27 '12 at 19:40
  • @BGM, It is meaningless to speak abot XML transformation, when you don't know the XML document on which the transformation must be applied. – Dimitre Novatchev Dec 27 '12 at 19:43
  • Dimitre, by "matched field" I mean where it says, ` – bgmCoder Dec 27 '12 at 19:48
  • @BGM, You can get the XML document -- just use: `` .I wonder how anyone can "write a transformation" if they don't have the source XML document this transformation must be applied upon. – Dimitre Novatchev Dec 27 '12 at 20:15
  • Could you take another look? I added some of the xml outputted by your query. – bgmCoder Dec 27 '12 at 21:27
  • @BGM, Sorry, but this isn't sufficient information. It *seems* to me that when the template matches a particular `FieldRef` you wantto find some other elements in the document, whose `name()` or `Name` attribute have the same value as the `Name` attribute of the currently-matched element. However, I cant see such other elements in the provided XML document. Also, if you cannot explain which other elements you want to select, are you sure that you know what you want? – Dimitre Novatchev Dec 27 '12 at 21:57
  • Oh, this is soooo hard! There is a big list with columns whose names are `Budget0`, `Scope`, `Risk` and `Schedule`. I only want to add a css class to them using a single function. I'll just go back to using the same stupid function four different times. Thanks for your help Dimitre. – bgmCoder Dec 27 '12 at 22:45
  • @BGM, If you know the XML document, then this certainly can be done with XSLT. – Dimitre Novatchev Dec 27 '12 at 22:53
  • Wow, I've tried all three of these lines and they each seem to crash the entire web part. Dimitre, are you still around? – bgmCoder Aug 04 '13 at 04:04
  • Hi Dimitre. It's just the standard Sharepoint fldtypes.xsl page - anybody who knows anything about Sharepoint knows all about it. – bgmCoder Aug 04 '13 at 05:02
  • @BGM, It isn't reasonable to expect XSLT experts to know anything about SharePoint. – Dimitre Novatchev Aug 04 '13 at 14:59
  • Maybe to a degree (which is why I tagged my question `sharepoint` - but they are usually pretty good about being able to abstract a little, and have gotten other answers here. Anyway, it's solved now, and it's there for the record in case anyone else needs it. – bgmCoder Aug 04 '13 at 22:30
0

Ah, after hours and hours and hours and days and months, here is an example (which I fiddled myself with help from this thread):

These two lines are the keys (Dimitre's answer was close):

<xsl:param name="thisNode" select="."/>
<xsl:variable name="currentValue" select="$thisNode/@*[name()=current()/@Name]" />

Here is the entire function, which reads two different columns and applies the values to either one:

<xsl:template match="FieldRef[@Name='YesNo1']|FieldRef[@Name='YesNo2']" mode="body">
    <xsl:param name="thisNode" select="."/>

    <xsl:variable name="currentValue" select="$thisNode/@*[name()=current()/@Name]" />
    <xsl:variable name="yesvalue">Yes</xsl:variable>
    <xsl:variable name="novalue">No</xsl:variable>

    <xsl:choose>
        <xsl:when test="contains($currentValue, $yesvalue)">
            <span class="yesno yes"><xsl:value-of select="$currentValue" /></span>
        </xsl:when>
        <xsl:when test="contains($currentValue, $novalue)">
            <span class="yesno no"><xsl:value-of select="$currentValue" /></span>
        </xsl:when>
    <xsl:otherwise>
            <span class="yesnoN"><xsl:value-of select="$currentValue" /></span>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template> 
Community
  • 1
  • 1
bgmCoder
  • 6,205
  • 8
  • 58
  • 105
  • Seems you've found an answer that works for you... I had a related but slightly different problem, and found [this answer](http://stackoverflow.com/a/585290/313756) to perfectly match it. Leaving that here in case others, like me, find this question before they find the other. (short version: `` was what I wanted.) – lindes Oct 14 '13 at 18:08