Solved

XSL max/string compare

Posted on 2009-07-14
10
1,128 Views
Last Modified: 2013-11-18
So I've got a SharePoint list of items, some of which have a Comment and all of which are associated with a Step.
The Step field is essentially a lookup on another table's column which incorporates the sort value followed by the step name.

I need to pull only the valid Comment associated with the highest sort value embedded in the Step

Problem is that the comments are not always present, and the steps are not always in the same order as the IDs, so position() is out.

My last attempt with a xsl:sort is in the CODE section below.  The substring-before(substring-after( part filters out empty comments (<div></div>)

Any Ideas?
<xsl:for-each select="$Dates[substring-before(substring-after(@Comment,'&gt;'),'&lt;') !=''][1]">

	<xsl:sort select=. data-type="text" order=descending/>

	<xsl:value-of select="substring-before(substring-after(@Comment,'&gt;'),'&lt;')"/>

</xsl:for-each>

Open in new window

0
Comment
Question by:RobertNoble
  • 6
  • 4
10 Comments
 
LVL 11

Assisted Solution

by:andrei_teodorescu
andrei_teodorescu earned 120 total points
ID: 24859447
Please provide more code and also a simple representation of your data
And what do you intend with select="$Dates[substring-before(substring-after(@Comment,'>'),'<') !=''][1]"

if you want to test for a variable if is empty or not, in your case:
<xsl:if test="substring-before(substring-after(@Comment,'>'),'<')">
0
 

Author Comment

by:RobertNoble
ID: 24860148
Below is what the code looks like now.  It's functional, but pulls up ALL comments instead of only the most 'recent' one.

You're right, the != '' at the end of the test and for-each can be dropped without affecting the outcome.

If i'm not mistaken, the XSLT receives the data from 3 sharepoint lists in the following (abbreviated) forma, where the 3rd references the other 2t:

<Packages>
      <Rows>
            <Row>
                  <Package>
                        <PackageName>A</PackageName>
                  </Package>
                  <Package>
                        <PackageName>B</PackageName>
                  </Package>
                  <Package>
                        <PackageName>C</PackageName>
                  </Package>
            </Row>
      </Rows>
</Packages>
<ProcessSteps>
      <Rows>
            <Row>
                  <Step>
                        <StepName>1 - x</StepName>
                  </Step>
                  <Step>
                        <StepName>2 - y</StepName>
                  </Step>
                  <Step>
                        <StepName>3 - z</StepName>
                  </Step>
            </Row>
      </Rows>
</ProcessSteps>
<Dates>
      <Rows>
            <Row>
                  <Date>
                        <Package>A</Package>
                        <Step>1 - x</Step>
                        <Comment>blah 1</Comment>
                  </Date>
                  <Date>
                        <Package>A</Package>
                        <Step>2 - y</Step>
                        <Comment>blah 2</Comment>
                  </Date>
                  <Date>
                        <Package>B</Package>
                        <Step>1 - x</Step>
                        <Comment>blah 3</Comment>
                  </Date>
            </Row>
      </Rows>
</Dates>

Basically at the end the row (for-each package) I want to display the comment whose step index (before the '-') is highest.
My current code will give me, in the case of Package A: "blah 1 blah 2" when I want only "blah 2"

* there is more data in all of the lists, but these fields are the ones used in this part of the stylesheel.
<xsl:choose>

	<xsl:when test="count($Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')])">

		<xsl:for-each select="$Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')]">

			<xsl:value-of select="substring-before(substring-after(@Comment,'&gt;'),'&lt;')"/><br/>

		</xsl:for-each>

	</xsl:when>

	<xsl:otherwise>

		-<!-- NO VALUE TEXT HERE -->

	</xsl:otherwise>

</xsl:choose>

Open in new window

0
 
LVL 11

Assisted Solution

by:andrei_teodorescu
andrei_teodorescu earned 120 total points
ID: 24865125
you still need to sort, but you have to sort before making the test
I still don't get it; the DVWP is showing data from a list or from an aggregate of 3 lists? You said that some columns are lookup type...
0
 

Author Comment

by:RobertNoble
ID: 24872013
For the sort, idk how to get it to grab the first element only... using [1] grabs the first element before sorting the data.
You're correct, The data source is joined, and was created in SPD 2007.  
The reason is that the row headers are in one list, the column headers in another, and the data in a 3rd list for a pseud-franken-crosstab view.
Maybe using a siblings-type function or ddwrt:max could be helpful? But I've no experience or idea how to use these, and have not had time to look it up yet.
0
 
LVL 11

Expert Comment

by:andrei_teodorescu
ID: 24872120
please provide me with some more info; how are the lists defined in SHP and the source code of your DVWP
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:RobertNoble
ID: 24879193
here's the declarations of the variables from the previous code.

what do you mean "how are the lists defined?"  I setup a joined datasource in SPD 2007 with the fields I needed for the view.
// Defined at the top of the <XSL>

<xsl:variable name="Dates" select="/dsQueryResponse/RFPDates2/Rows/Row"/>

// Defined at the beginning of each <TR> before calling the date-calling template

<xsl:with-param name="Pkg" select="@Package_x002e_FullName"/>

<!-- -->

<xsl:choose>

        <xsl:when test="count($Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')])">

                <xsl:for-each select="$Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')]">

                        <xsl:value-of select="substring-before(substring-after(@Comment,'&gt;'),'&lt;')"/><br/>

                </xsl:for-each>

        </xsl:when>

        <xsl:otherwise>

                -<!-- NO VALUE TEXT HERE -->

        </xsl:otherwise>

</xsl:choose>

Open in new window

0
 

Author Comment

by:RobertNoble
ID: 24879213
I'm basically iterating through the parent lists for each of the packages and steps, since there is not necessarily a date item which matches each pkg/step pair, and need blank space to be present when this is the case.
0
 

Author Comment

by:RobertNoble
ID: 24895023
My latest thought was to use ddwrt:max() on the lookup value and test if it matches the current value to display only th highest value.  The pseudocode is commented out cause I can't seem to get it to work properly.

The datestep field is a lookup to another list, where it combined a sort value and a title.  I've tried using substring to extract only the number and convert it back to an int with number() to apply max() but with no success.
<xsl:when test="count($Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')])">

     <xsl:for-each select="$Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')]">

<!-- If this->datestep = max(datestep) then do the following display -->

          <xsl:value-of select="substring-before(substring-after(@Comment,'&gt;'),'&lt;')"/><br/>

     </xsl:for-each>

</xsl:when>

Open in new window

0
 

Accepted Solution

by:
RobertNoble earned 0 total points
ID: 24895100
I've got it.  for future reference.

The key is taking only the first element AFTER sorting the data.  using a [1] in the for-each doesn't work, because the data only gets sorted after that condition is filled.

by keeping only position() = 1 using and if clause after sorting descending, only the highest-value step is kept (since the step name is prefixed with a sort index)

Code Below
<xsl:when test="count($Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')])">

	<xsl:for-each select="$Dates[@Package = $Pkg and substring-before(substring-after(@Comment,'&gt;'),'&lt;')]">

	<xsl:sort select="@DateStep" order="descending"/>

		<xsl:if test="position() = 1">

			<xsl:value-of select="substring-before(substring-after(@Comment,'&gt;'),'&lt;')"/>

		</xsl:if>

	</xsl:for-each>

</xsl:when>

Open in new window

0
 
LVL 11

Expert Comment

by:andrei_teodorescu
ID: 24895142
Hi,

Sorry, but I had other things over my head during the past days; glad you found your answer.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
These days socially coordinated efforts have turned into a critical requirement for enterprises.
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
The viewer will learn how to dynamically set the form action using jQuery.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now