Solved

XSL max/string compare

Posted on 2009-07-14
10
1,145 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Office 365 Training for Admins - 7 Day Trial

Learn how to provision tenants, synchronize on-premise Active Directory, implement Single Sign-On, customize Office deployment, and protect your organization with eDiscovery and DLP policies.  Only from Platform Scholar.

 

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
 

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

Office 365 Training for Admins - 7 Day Trial

Learn how to provision tenants, synchronize on-premise Active Directory, implement Single Sign-On, customize Office deployment, and protect your organization with eDiscovery and DLP policies.  Only from Platform Scholar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SBS 2011 Need to move SharePoint Foundation datab ases 2 38
Wordpress Hacked 1 87
Sharepoint list to Access database 9 80
Need to update SSL certificate on SBS 2011 7 83
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
A recent project that involved parsing Tableau Desktop and Server log files to extract reusable user queries for use in other systems. I chose to use PowerShell to gather the data, and SharePoint to present it...
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

751 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