Copy an element and truncate it with xslt - xslt

I am trying to select all the table cells in a particular column and truncate them down to 10 characters.
I really can't fault this syntax.
<xsl:template match="table[contains(#class, 'listing')]//tr/td[contains(#class, 'listing-body-start')]">
<td>
<xsl:value-of select="substring(./text(), 1, 10)"/>
</td>
</xsl:template>
I can replace the contents of the cell with static text, or replicate the same text by using select=".", but as soon as I try this substring method, the cells dissappear.

Try to avoid using text(). It's generally bad practice.
Use
<xsl:value-of select="substring(., 1, 10)"/>
This works on the string value of the td element, rather than on its child text nodes. In many content models it would be normal for a td element to contain other elements as children, e.g. a p or para element, and in that case looking for the child text nodes will fail.
This answer is a guess. If you don't tell us what's in your input, we have no choice but to guess.

Related

how to count the value of multiple elements in xslt

I have this xslt code to count the abstract length of type main:
<xsl:variable name="mainAbstract">
<xsl:value-of select="string-length(normalize-space(abstract[#type = 'main']))"/>
</xsl:variable>
and I had an issue where I had multiple xml tags that matches the same pattern and it's not working.
How should I count the number of characters in multiple elements from this select statement?
If you have multiple abstract elements of type main, then you need to select which one you want to process.
If - as it seems - you want the sum of their individual string-lenghts, then do:
<xsl:value-of select="sum(abstract[#type = 'main']/string-length(normalize-space()))"/>

fetch value from the input message (this message doesn't have any space)

I have a input string like this,without any space
51=2MA011362X17=MG127AJ4015AG1A20=022=M35=U48=9CVRVC449
Here, number before = is key and after is value. From this string I have to fetch value of 17= (basically fetch the value MG127AJ4015AG1A)
I used <xsl:value-of select="substring-before(substring-after(.,'17='), '=')"/> which is giving me result: MG127AJ4015AG1A20, now I am stuck with removing these last 2 numeric values (20). totally confused how this an be achieved.
Final output string should be - MG127AJ4015AG1A
If it is the case that the number at the end will always be two digits, you put your current expression in a variable, and use substring to remove the last two characters, like so:
<xsl:variable name="match" select="substring-before(substring-after(.,'17='), '=')" />
<xsl:value-of select="substring($match, 1, string-length($match) - 2)"/>

xslt mapping to find substring between

I have my string as below
<Text>Pack:NA Lead:20 Dimension:235</Text>
And need to map
NA to outputfield1
20 to outputfield2
235 to outputfield3
How to do this correctly in xslt mapping where the values 'NA,20,235' could be different each time?
I could only see substring component which takes length as second parameter.
That leads requires several steps to achieve this.
Any better solution to just take the value between Lead: and Dimension for outputfield2?
To extract the Pack value, you can use:
<xsl:value-of select="substring-before(substring-after(Text, 'Pack:'), ' ')" />
To extract the Lead value, use:
<xsl:value-of select="substring-before(substring-after(Text, 'Lead:'), ' ')" />
To extract the Dimension:
<xsl:value-of select="substring-after(Text, 'Dimension:')" />

Get position of specific word

I am new in XSLT and if it is possible to get the position of a specific word? For example, I have a data like this:
<Data>The quick brown fox jumps over the lazy dog!</Data>
I want to get the position of a "brown", "over", "dog" and "!". And, store it in different output name. Like the position of brown is <foo>3</foo>, position of over is <boo>6</boo>, dog <hop>9</hop> and ! <po_df>10</po_df>. Is it possible?
If you were only looking for words you could use tokenize(., '\s+|\p{P}')
<xsl:template match="Data">
<xsl:copy>
<xsl:variable name="words" select="tokenize(., '\s+|\p{P}')"/>
<xsl:for-each select="'brown', 'over', 'dog'">
<matched item="{.}" at-pos="{index-of($words, .)}"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
which gives
<Data>
<matched item="brown" at-pos="3"/>
<matched item="over" at-pos="6"/>
<matched item="dog" at-pos="9"/>
</Data>
so it has the right positions (I am not sure where the names of the elements you posted (like hop) are to be taken from so I have not tried to implement that.).
As you also want to identify a punctuation character I am not sure tokenize suffices and even with analyze-string it is not straight-forward to match and collect the position. Maybe someone else has a better idea.

XSL:Number count not working as expected -- Issue with my XPath?

Here's the XML
<row>
<cell>blah blah</cell>
<check>
<option/>
<option/>
<option/>
<option/>
<option/>
<option/>
</check>
</row>
Here is the XSL
<xsl:template match="row">
<xsl:variable name="inputLevel">
<xsl:number count="option" level="any" from="."/>
</xsl:variable>
<xsl:value-of select="$inputLevel"/>
</xsl:template>
All I get is "0". http://www.w3schools.com/XPath/xpath_syntax.asp says "." means the current node. Shouldn't it be returning "6"?
Edit1: I wanted to look for option tags at ANY level, not just check. Should have explained but the option tags could exist at any level below
If you want to count descendant options you shouldn't use xsl:number but:
<xsl:variable name="inputLevel" select="count(.//option)">
I think the problem is that the xpath expression option won't match anything at the row element - try this instead:
<xsl:number count="check/option" level="any" from="." />
To look for option elements at any level use the following syntax:
<xsl:number count="//option" level="any" from="." />
I don't think the from attribute is reqired, and the level attribute probably isn't doing what you think it is (I'm also not sure what it does...)
From the XSLT 1.0 W3C specification:
"If no value attribute is specified, then the xsl:number
element inserts a number based on the
position of the current node in the
source tree. The following
attributes control how the current
node is to be numbered:
The levelattribute specifies what
levels of the source tree should be
considered; it has the values
single, multiple or any. The
default is single.
The count attribute is a pattern
that specifies what nodes should be
counted at those levels. If count
attribute is not specified, then it
defaults to the pattern that matches
any node with the same node type as
the current node and, if the current
node has an expanded-name, with the
same expanded-name as the current node
When level="any", it constructs a
list of length one containing the
number of nodes that match the count
pattern and belong to the set
containing the current node and all
nodes at any level of the document
that are before the current node in
document order, excluding any
namespace and attribute nodes (in
other words the union of the members
of the preceding and ancestor-or-self
axes). If the from attribute is
specified, then only nodes after the
first node before the current node
that match the from pattern are
considered. ".
From this text it is clear that only nodes that are ancestors or are preceding the current node are counted.
In this question, the current node is the top element node row and it has 0 ancestor and 0 preceding element nodes.
Therefore, the returned result is correct!
Solution:
Use:
count(descendant::option)
The result of evaluating this expression is the count of all option elements in the document, that are descendents of the current node (the row element).