how to distinguish <br> inside <h5>? - xslt

could you help me with this problem please?
part of input xml:
<h5 class="Paragraf">
§ 113 a 114
<br/>
zrusen
</h5>
what would I like to have on output:
§ 113 a 114 -> A_Header_5
zrusen -> A_Header_5-Podnadpis
part of xslt condition which I created but it’s not doing what I want:
<xsl:when test="(self::h5) and not (child::br)">A_Header_5</xsl:when>
<xsl:when test="(self::h5) and (child::br)">
<xsl:if test="text()[1]">A_Header_5</xsl:if>
<xsl:if test="text()[2]">A_Header_5-Podnadpis</xsl:if>
</xsl:when>
unfortunately output with this xslt conditions looks this:
§ 113 a 114 -> A_Header_5A_Header_5-Podnadpis
zrusen -> A_Header_5A_Header_5-Podnadpis
Thank you

This is not exactly the same logic as in your post, but without a full _ Minimal, Complete, and Verifiable example_ it is hard to spot the root cause of your dissatisfaction with your code.
The following code iterates over all text() nodes and distinguishes on the basis of the existence of a following <BR /> element.
XSLT 1.0:
<xsl:template match="h5">
<xsl:for-each select="text()">
<xsl:if test="."><xsl:value-of disable-output-escaping = "yes" select="concat(normalize-space(.),' -> ')" /></xsl:if>
<xsl:if test="following-sibling::br">A_Header_5</xsl:if>
<xsl:if test="not(following-sibling::br)">A_Header_5-Podnadpis</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
Output:
§ 113 a 114 -> A_Header_5
zrusen -> A_Header_5-Podnadpis

Related

ready.mobi mobile readiness nesting xsl tags appropriately?

I've been trying to change my code for a while now and have failed to do so.
I am able to get the readiness score to peak at 3.72 and have the code display and function well here:
link removed
But when used with ready.mobi:
ready.mobi/launch.jsp?locale=en_EN#fragment-1
I get the following errors:
FAIL near line -1 column -1
Your page does not validate against XHTML Basic 1.1 or XHTML Mobile Profile 1.2
FAIL near line 41 column 17
The content of element type "a" must match "(br|span|em|strong|dfn|code|samp|kbd|var|cite|abbr|acronym|q|tt|i|b|big|small|sub|sup|img|object|input|select|textarea|label|button|script|noscript)".
FAIL near line 46 column 17
*same element type "a" error line
FAIL near line 51 column 17
*same element type "a" error line
FAIL near line 56 column 17
.....
FAIL near line 61 column 17
...
Because of the markup errors, the xhtml mobile profile fails as well.
But having said that, my score can be a 5 with both xhtml mobile profile and markup valid if the code is like the following:
link removed
The nesting order is changed for the validator to accept. However, this causes the links to be broken.
Before:
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="p"><xsl:attribute name="class"><xsl:text>more</xsl:text></xsl:attribute><xsl:text>more...</xsl:text></xsl:element>
After:
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:element name="p"><xsl:attribute name="class"><xsl:text>more</xsl:text></xsl:attribute><xsl:text>more...</xsl:text></xsl:element>
</xsl:element>
Any help will be appreciated. :)
Many thanks!!!
What about if you put the <a> inside the <p>?
<xsl:element name="p"><xsl:attribute name="class"><xsl:text>more</xsl:text></xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:text>more...</xsl:text></xsl:element>
</xsl:element>
or much more simply, using literal result elements and an attribute value template for the href:
<p class="more">more...</p>

XSLT xsl:apply-templates Conditional Syntax

I've got the following XSLT code which lists out the folders and their file items from a specified node.
This all works fine but I'd like to parameterise the page and optionally filter its output by a tag value.
Being an XLST numpty I'm stumped with the syntax for the conditional I should be putting in under the <xsl:when test="$tag"> clause - can someone please help ?
<xsl:variable name="tag" select="umbraco.library:Request('tag')" />
<xsl:template match="/">
<!-- Root folder in Media that holds the folders to output -->
<xsl:variable name="mediaRootFolderId" select="5948" />
<!-- Pass in true() to get XML for all nodes below -->
<xsl:variable name="mediaRootNode" select="umbraco.library:GetMedia($mediaRootFolderId, true())" />
<xsl:choose>
<xsl:when test="$tag">
</xsl:when>
<xsl:otherwise>
<!-- If we didn't get an error, output Folder elements that contain Image elements -->
<xsl:apply-templates select="$mediaRootNode[not(error)]/Folder[File]" >
<xsl:sort select="#nodeName"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Template for folders -->
<xsl:template match="Folder">
<div class="folder">
<h2>Folder: <xsl:value-of select="#nodeName" /></h2>
<div class="images">
<xsl:apply-templates select="File">
<xsl:sort select="#nodeName"/>
</xsl:apply-templates>
</div>
</div>
</xsl:template>
<!-- Template for files -->
<xsl:template match="File">
File: <a href="{umbracoFile}" alt="{#nodeName}" ><xsl:value-of select="#nodeName" /></a> <br/>
</xsl:template>
Instead of the long <xsl:choose> instruction, use:
<xsl:apply-templates select=
"$mediaRootNode[not($tag)][not(error)]
/Folder[File]" >
Explanation: For the XPath expression in the select attribute above to select a non-empty set of nodes it is necessary that boolean($tag) is true(). Thus the above single <xsl:apply-templates> instruction is equivalent to the long <xsl:choose> in the question.
you can test if $tag is set like this.
<xsl:param name="tag">
<xsl:message terminate="yes">
$tag has not been set
</xsl:message>
</xsl:param>
This isn't standard though, it'll work on most XSLT processors though.
If you wanted to be absolutely save, you could set the value to an illegal value (such as 1 div 0) and test for it in the body of the template:
<xsl:param name="tag" select="1 div 0" />
<xsl:if test="$tag = 1 div 0">
<xsl:message terminate="yes">
$tag has not been set, or has been set to Infinity, which is invalid.
</xsl:message>
</xsl:if>
Source: O'Reilly XSLT Cookbook

xsl:variable contains nodeset. How to output nth node of variable?

I am transforming an XML document. There is an attribute #prettydate that is a string similar to "Friday, May 7, 2010". I want to split that string and add links to the month and the year. I am using the exslt:strings module and I can add any other necessary EXSLT module.
This is my code so far:
<xsl:template match="//calendar">
<xsl:variable name="prettyparts">
<xsl:value-of select="str:split(#prettydate,', ')"/>
</xsl:variable>
<table class='day'>
<thead>
<caption><xsl:value-of select="$prettyparts[1]"/>,
<a>
<xsl:attribute name='href'><xsl:value-of select="$baseref"/>?date=<xsl:value-of select="#highlight"/>&per=m</xsl:attribute>
<xsl:value-of select='$prettyparts[2]'/>
</a>
<xsl:value-of select='$prettyparts[3]'/>,
<a>
<xsl:attribute name='href'><xsl:value-of select="$baseref"/>?date=<xsl:value-of select="#highlight"/>&per=y</xsl:attribute>
<xsl:value-of select='$prettyparts[4]'/>
</a>
</caption>
<!--etcetera-->
I have verified, by running $prettyparts through a <xml:for-each/> that I am getting the expected nodeset:
<token>Friday</token>
<token>May</token>
<token>7</token>
<token>2010</token>
But no matter which way I attempt to refer to a particular <token> directly (not in a foreach) I get nothing or various errors to do with invalid types. Here's some of the syntax I've tried:
<xsl:value-of select="$prettyparts[2]"/>
<xsl:value-of select="$prettyparts/token[2]"/>
<xsl:value-of select="exsl:node-set($prettyparts/token[2])"/>
<xsl:value-of select="exsl:node-set($prettyparts/token)[2]"/>
Any idea what the expression ought to be?
ETA: Thanks to #DevNull's suggestion, the correct expression is:
<xsl:value-of select="exsl:node-set($prettyparts)[position()=2]"/>
and, I have to set the variable this way:
<xsl:variable name="prettyparts" select="str:split(#prettydate,', ')" />
Try using [position()=2] instead of [2] in your predicates.
Example:
<xsl:value-of select="$prettyparts[position()=2]"/>

XSLT: opening but not closing tags

Is there a way to open a tag and not close it? For example:
<xsl:for-each select=".">
<span>
</xsl:for-each>
This is my code: http://pastebin.com/1Xh49YN0 . As you can see i need to open on a when tag and close it on another when tag (row 43 and 63).
This piece of code is not valid because XSLT is not well formed, but is there a way to do a similar thing? Thank you
Move the content between the two existing xsl:choose elements to a new template
In the xsl:when, open and close your span. Inside the span, call this new template.
Add an xsl:otherwise to the xsl:choose, in this, call the template, without adding a span.
As a general point, try to use xsl:apply-templates a bit more often, rather than xsl:for-each, it should make it easier to understand what is going on.
You can't - XSLT isn't about generating a text file or a sequence of characters, it's about transforming one document tree into another. That the tree eventually gets serialized into a textual format is incidental.
This is why, for example, you can't choose between and in the output file - they're both represent exactly the same document tree.
You can almost always achieve what is intended by refactoring into separate templates that call each other.
You can use disable-output-escaping, but it's generally considered a bit of a hack, and I understand it's deprecated in XSLT 2.
Untested, obviously, but if I understood your original code correctly, this should be pretty close.
<xsl:choose>
<xsl:when test="$pos">
<xsl:for-each select="$s">
<xsl:choose>
<!-- inizio contesto -->
<xsl:when test="$pos[.=position()+$context_number]">
<xsl:text>INIZIO CONTESTO</xsl:text>
</xsl:when>
<!-- fine contesto -->
<xsl:when test="$pos[.=position()-$context_number]">
<xsl:text>FINE CONTESTO</xsl:text>
</xsl:when>
<!-- parola -->
<xsl:when test="$pos[.=position()]">
<span class="word"><xsl:value-of select="."/></span>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<!-- stampo tutta la riga -->
<xsl:value-of select="$s"/>
</xsl:otherwise>
</xsl:choose>
Hint: <xsl:when test="(. - $current_pos) eq 0"> is equivalent to <xsl:when test=".=$current_pos">. ;-)

Conditional statements in xsl

I working on a site which some if/or statements in XSL and being a little unfamilar with the language i'm not certain how to accomplish:
if [condion one is met] or [condition two is met] then do [action] otherwise do [alternative action]
can anyone offer some examples?
Thanks in advance!
Conditionals in XSLT are either an unary "if":
<xsl:if test="some Boolean condition">
<!-- "if" stuff (there is no "else" here) -->
</xsl:if>
or more like the switch statement of other languages:
<xsl:choose>
<xsl:when test="some Boolean condition">
<!-- "if" stuff -->
</xsl:when>
<xsl:otherwise>
<!-- "else" stuff -->
</xsl:otherwise>
</xsl:choose>
where there is room for as many <xsl:when>s as you like.
Every XPath expression can be evaluated as a Boolean according to a set of rules. These (for the most part) boil down to "if there is something -> true" / "if there is nothing -> false"
the empty string is false
0 is false (so is NaN)
the empty node set is false
the result of false() is false
every other literal value is true (most notably: 'false' is true and '0' is true)
the result of expressions is evaluated with said rules (no surprise here)
Edit: There is of course a more advanced (and more idiomatic) method to control program flow, and that's template matching:
<xsl:template match="node[contains(., 'some text')]">
<!-- output X -->
</xsl:template>
<xsl:template match="node[not(contains(., 'some text'))]">
<!-- output Y -->
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select=".//node" />
</xsl:template>
Writing templates that match specific nodes and using <xsl:apply-templates> to make the XSLT processor choose the appropriate ones is superior to writing complex <xsl:if> or <xsl:choose> constructs.
The above sample is equivalent to the imperative style:
<xsl:template match="/">
<xsl:for-each select=".//node">
<xsl:choose>
<xsl:when test="contains(., 'some text')">
<!-- output X -->
</xsl:when>
<xsl:when test="not(contains(., 'some text'))">
<!-- output Y -->
</xsl:when>
<xsl:choose>
<xsl:for-each>
</xsl:template>
XSLT beginners tend to pick the latter form for its familiarity, but examining template matching instead of using conditionals is worthwhile. (also see.)
XSL has an <xsl:if>, but you're probably looking more for a <xsl:choose> / <xsl:when> / <xsl:otherwise> sequence. Some examples here (near the bottom). Maybe:
<xsl:choose>
<xsl:when test="[conditionOne] or [conditionTwo]">
<!-- do [action] -->
</xsl:when>
<xsl:otherwise>
<!-- do [alternative action] -->
</xsl:otherwise>
</xsl:choose>
The general if statement syntax is
<xsl:if test="expression">
...some output if the expression is true...
</xsl:if>
Not sure if XSL has the else condition but you should be able to test if true then test if false or the other way around.
In this case you would have to use a xsl:choose. It's like using if/else with a final else.
<xsl:choose>
<xsl:when test="condition one or condition two">
<!-- action -->
</xsl:when>
<xsl:otherwise>
<!-- alternative action -->
</xsl:otherwise>
</xsl:choose>