How do I address an item in a sequence when using tokenize() - xslt-3.0

I have an HTML that contains a style attribute with a list of values separated by semicolons:
<td style="border-width:1pt;border-color:#FFFFFF;border-style:solid">
I want to split this list:
<xsl:variable name="astyle"><xsl:value-of select="tokenize(#style, ';')"/></xsl:variable>
This gives me a sequence. Now I want to select the first item in the sequence.
<xsl:value-of select="$astyle[1]"/>
result:
"border-width:1pt border-color:#FFFFFF border-style:solid"
so that's the entire sequence instead of the first item in the sequence.
I can't find any documentation on this.
Edit: it seems my assumption is incorrect. Tokenize() contains a sequence of 1 item. I was expecting 3 items.
How can I split a string into items that can be addressed individually?
I want to do something like
<xsl:value-of select="$astyle[1]"/>
and get:
border-width:1pt

Use <xsl:variable select="tokenize(...)" name="astyle"/>, then the value of the variable is a sequence and $astyle[1] works.

Related

Replace alphabets with spaces

I want to print item.rate but only with having integer values in it.Currently it is printing the rate and also the currency in character.I want to hide the chars.
<td> ${item.rate} </td>
You should be able to use Freemarker's replace function. See https://freemarker.apache.org/docs/ref_builtins_string.html#ref_builtin_replace for reference.
I'd recommend using a regular expression to find everything that's not a number. That should look something like:
${item.rate}?replace('\D', '', 'r')
Reference for Freemarker's regular expression syntax is here: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

Return result with concatenated string

I want to write a xquery statement that returns a number plus a string called " books". Like this:
<table>
<tr><td>300 books</td></tr>
<tr><td>145 books</td></tr>
</table>
I've started writing the code, but it doesn't work...
<tr><td>{$num + 'books'}</td>
Any help with this?
Move the literal string " books" outside of the expression:
<tr><td>{$num} books</td></tr>
Or you could create a sequence of items by enclosing it inside of parenthesis and separating with a comma:
<tr><td>{($num, 'books')}</td></tr>
Or you could concatenate the items (notice the leading space):
<tr><td>{concat($num, ' books')}</td></tr>

Why does d3.select() return array of array?

I recently started using d3.js to write some scripts to manipulate SVGs. So most of the time I refer d3 documentation and find the solution. However I cannot understand why d3.select function return array of arrays. For example let's say i have an SVG element and if I do d3.select("svg"), it returns [[svg]] so I have to do d3.select("svg")[0]. The documentation says
One nuance is that selections are grouped: rather than a one-dimensional array, each
selection is an array of arrays of elements. This preserves the
hierarchical structure of subselections
Then says we can ignore it most of the time.
Why does it return array of array ?
What does
This preserves the hierarchical structure of subselections
mean?
Thanks in advance.
You shouldn't need to know or care how the object d3.select returns is structured internally. All you need to know is which methods are accessible in that object, which is what the documentation describes.
Say you have this document:
<div>
<span>1</span>
<span>2</span>
</div>
<div>
<span>3</span>
<span>4</span>
</div>
If you select all <div> elements with d3.selectAll
var div = d3.selectAll("div");
the div is a d3 selection object of size 2, one for each <div> element in the document.
But if you now generate a subselection from this selection object
var span = div.selectAll("span");
a search is made for matching elements within each element in the div selection, and the structure is preserved -- i.e., the span selection will contain the same number of elements as the div selection it was based on, and each of these will consist of a selection of elements found in that element.
So in this case, span will contain two selections (first <div> and second <div>), each of which will contain two elements(1 and 2 in the first, 3 and 4 in the second).
As for select, it is the same as selectAll except it stops after finding one match; its return is structured exactly the same way, however.
Demo

XSLT equation using SP list fields

I have a SP Dataview that I have converted to XSLT, so that I could add a header displaying a percentage (Complete). Before I converted the dvwp to xslt, I added two count headers- one on Complete, and another on LastName. They worked wonderfully- showing me the # of records and the # of records with a value in the complete field. However, when I converted the dv to xslt I realized that I lost my headers :(
So, I am adding them back in using xslt. Currently the XPath code for the equation that I have is <xsl:value-of select="count($Rows) div count($Rows)" />.
How do I get the total # of Yes values that are in my Complete field?
UPDATE1:
Found this http://www.endusersharepoint.com/STP/viewtopic.php?f=14&t=534 and tried it, however causes the following error- Failed setting processor stylesheet: 0x80004005: Argument 1 must return a node-set. -->count(/dsQueryResponse/Rows/Row='Y')<--
UPDATE2:
Complete is the name of a field w/i my XSLT dataset. The return type is either Y or blank. For grins I tried <xsl:value-of select="count(/xpath/to/parent/element[#Complete eq 'Y']) div count($Rows)" /> however I recieved the following error- Failed setting processor stylesheet: 0x80004005: Expected token ']' found 'NAME'.count((/xpath/to/parent/element[#Complete -->eq <--'Y']) div count($Rows) Am starting to think that there may be a problem w/ 'eq'.... Referencing my XML operators...
UPDATE3:
<xsl:value-of select="count(/xpath/to/parent/element[#Complete = 'Y']) div count($Rows)" />
Okay so it still says 0, but I think the reason why it's not showing the correct answer is b/c it is expecting to show an integer, and obviously the value being returned from the equation is going to be a decimal... Have been fiddling with the equation in XPath... here's what I've tried-
count(/xpath/to/parent/element[#Complete = 'Y']) div count($Rows)*100
(count(/xpath/to/parent/element[#Complete = 'Y']) div count($Rows))*100
100(count(/xpath/to/parent/element[#Complete = 'Y']) div count($Rows))
UPDATE4:
So I know my previous thought that the correct number not showing b/c it was a float is not correct, as all numbers in XPath and XSLT 1.0 are floats. Reference
UPDATE5:
Upon further investigation, I have found that the problem lies with the count(/xpath/to/parent/element[#Complete = 'Y']) part of my equation, as this is returning 0 instead of a value. [i know i have at least 3 'Y' vals in my Complete col]
UPDATE6:
<records*>
<record*>
<last_name></last_name>
<first_name></first_name>
<mi></mi>
<office_symbol></office_symbol>
<geo_location></geo_location>
<complete></complete>
<date_complete></date_complete>
<date_expires></date_expires>
<email></email>
<supervisor></supervior>
</record*>
</records*>
*i don't know what these nodes are called as my data is coming from a database and not an xml file, i just made up record/records
UPDATE7
Going back to my original question. I am still trying to find out the XPath equation to display the number of parents (record in the XML i posted above) where the complete node = Y.
UPDATE8
Ok. So I have edited and tested using http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=tryxsl_value-of. Working XSLT to count the # of Complete = Y is <xsl:value-of select="count(catalog/cd [complete = 'Y'])" /> so theen I put EXACTLY what works on W3schools into my SP Dataview and I get nothing... just an empty space. Why doesn't the code work in my SPDV?
If your "Complete" field is an element:
<xsl:value-of select="count(/xpath/to/complete/field/element[string(.) eq 'Yes])"/>
If your complete field is an attribute of an element:
<xsl:value-of select="count(/xpath/to/parent/element[#complete eq 'Yes'])"/>
Without knowing the structure of your XML I can't provide the specific XPATH required -- the predicate "[]" is what selects only the "Yes" values

Sharepoint XSLT Dynamic filtering

I'm trying to create a dynamic row filter based on a variable. I have the following code:
<xsl:variable name="filter" select="contain(#Title, 'title1') or contain(#Title, 'title2')"/>
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[string($filter)]" />
This unfortunately doesn't seem to work and I end up with all rows. I'm guessing the filter doesn't actually get applied, since I can copy and paste the output of the $filter variable, copy and paste it in the Row[] and it works as expected.
Anyone tried to do this before?
In case you're wondering the filter variable is actually created using a template that splits a string like:
title1 - title2 - title3
and returns a string like:
contain(#Title, 'title1') or contain(#Title, 'title2') or contain(#Title, 'title3')
Any help would be greatly appreciated!
You can't do what you seem to be attempting here. An XPath expression is atomical, you can't save parts of it and re-use them (apart from that it is contains(), not contain()).
You need something like this:
<xsl:variable name="Rows" select="
/dsQueryResponse/Rows/Row[
contains(#Title, 'title1') or contains(#Title, 'title2')
]
" />
Your "filter" does not work because if $filter is a string, then it is a string, nothing else. It does not get a magical meaning just because it looks like XPath. ;-)
This
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[string($filter)]" />
evaluates to a non-empty string as the predicate. And any non-empty string evaluates to true, which makes the expression return every node there is.
If you want a dynamic filter based on an input string, then do this:
<xsl:variable name="filter" select="'|title1|title2|title3|'" />
<xsl:variable name="Rows" select="
/dsQueryResponse/Rows/Row[
contains(
$filter,
concat('|', #Title, '|')
)
]
" />
The use of delimiters also prevents "title11" from showing up if you look for "title1".
Make sure your filter always starts and ends with a delimiter, and use a delimiter that is reasonably unlikely to ever occur as a natural part of #Title. (For example, you could use 
. If your title cannot be multi-line this is pretty safe.)

Resources