Is it possible to add text from a xsl variable to the inside of a html tag something like this?
<xsl:variable name="selected">
<xsl:if test="#class = 'selected'"> class="selected"</xsl:if>
</xsl:variable>
<li{$selected}></li>
Try this:
<xsl:element name="li">
<xsl:if test="#class = 'selected'">
<xsl:attribute name="class">
selected
</xsl:attribute>
</xsl:if>
</xsl:element>
Optionally, the xsl:if could be nested in the xsl:attribute, instead of the other way around, if a class="" is desired. As already mentioned, it is unwise to write this as literal text.
You should not attempt to write this as literal text, instead look at xsl:element and xsl:attribute. Rough example:
<xsl:element name="li">
<xsl:attribute name="class">
<xsl:value-of select="$selected" />
</xsl:attribute>
</xsl:element>
Full documentation here.
Note that if you are careful enough to make it its first child, you can use <xsl:attribute> directly inside of your <li> tag, instead of using <xsl:element>
<li>
<xsl:if test="$selected">
<!-- Will refer to the last opened element, li -->
<xsl:attribute name="class">selected</xsl:attribute>
</xsl:if>
<!-- Anything else must come _after_ xsl:attribute -->
</li>
Related
<a>
<xsl:attribute name="href">
<xsl:value-of select="/*/properties/property[#name='report']/#value" />
</xsl:attribute>
</a>
Is there any way to concat another string to
<xsl:value-of select="/*/properties/property[#name='report']/#value" />
I need to pass some text to href attribute in addition to the report property value
You can use the rather sensibly named xpath function called concat here
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('myText:', /*/properties/property[#name='report']/#value)" />
</xsl:attribute>
</a>
Of course, it doesn't have to be text here, it can be another xpath expression to select an element or attribute. And you can have any number of arguments in the concat expression.
Do note, you can make use of Attribute Value Templates (represented by the curly braces) here to simplify your expression
Three Answers :
Simple :
<img>
<xsl:attribute name="src">
<xsl:value-of select="//your/xquery/path"/>
<xsl:value-of select="'vmLogo.gif'"/>
</xsl:attribute>
</img>
Using 'concat' :
<img>
<xsl:attribute name="src">
<xsl:value-of select="concat(//your/xquery/path,'vmLogo.gif')"/>
</xsl:attribute>
</img>
Attribute shortcut as suggested by #TimC
<img src="{concat(//your/xquery/path,'vmLogo.gif')}" />
Use:
The easiest way to concat a static text string to a selected value is to use element.
<a>
<xsl:attribute name="href">
<xsl:value-of select="/*/properties/property[#name='report']/#value" />
<xsl:text>staticIconExample.png</xsl:text>
</xsl:attribute>
</a>
Easiest method is
<TD>
<xsl:value-of select="concat(//author/first-name,' ',//author/last-name)"/>
</TD>
when the XML Structure is
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
Not the most readable solution, but you can mix the result from a value-of with plain text:
<a>
<xsl:attribute name="href">
Text<xsl:value-of select="/*/properties/property[#name='report']/#value"/>Text
</xsl:attribute>
</a>
I'm new to XSLT, and there's one specific thing I don't know how to do, despite hours of searching for the answer.
I'm outputting blocks of HTML (result sets), and sometimes the result is a hyperlink, sometimes it is not.
The simple flow looks like this:
<a...> if #url
some HTML code
</a> if #url
But if I do:
when #url
<a...>
/when
some HTML code
when #url
</a>
/when
... I'm told that I have mismatched tags.
I was using CDATA text for the anchor set, but a lot of messages say that this is a "hack" approach.
I'm trying to avoid having to repeat the entire HTML code block only to include the anchors on only one of them.
How do I do this?
-------edit / additional info-----------
Does this make more sense?
<xsl:template match="Row">
<xsl:choose>
<xsl:when test="#url!=''">
<a><xsl:attribute name="href"><xsl:value-of select="#url" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<img />
<xsl:choose>
<xsl:when test="#url!=''">
</a>
</xsl:when>
</xsl:choose>
</xsl:template>
In XSLT, your output is a tree of nodes. Writing an element node is a single atomic operation; it can't be split into separate operations of writing a start tag and writing an end tag. You can't create half a node.
If you do try to treat <a> and </a> as separate and separable operations, you will get this error, because the stylesheet must be well-formed XML.
So, stand back and explain what you are trying to achieve, and then we can tell you how to achieve it properly in XSLT.
One way to refactor the XSLT to conditionally apply the hyperlink and not repeat the logic to produce the <img/> (or whatever more complex logic you are trying to avoid repeating) is to extract that logic out into a different template(s) as either a named template or a template with a #mode.
For instance:
<xsl:template match="Row">
<xsl:choose>
<xsl:when test="#url!=''">
<a>
<xsl:attribute name="href">
<xsl:value-of select="#url"/>
</xsl:attribute>
<xsl:apply-templates select="." mode="image"/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="image"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--The "common" logic to produce an image element, whether or not it will be surrounded by an anchor linking to the #url -->
<xsl:template match="Row" mode="image">
<img/>
</xsl:template>
An alternative way of accomplishing the same thing, but using templates instead of <xsl:choose>:
<xsl:template match="Row[#url]">
<a href="#url">
<xsl:apply-templates select="." mode="image"/>
</a>
</xsl:template>
<xsl:template match="Row">
<xsl:apply-templates select="." mode="image"/>
</xsl:template>
<xsl:template match="Row" mode="image">
<img/>
</xsl:template>
I have an xml with img tag
<img>
source
</img>
I want to generate:
<img src="source.jpg">
I tried something like that:
<img>
<xsl:attribute name="src">
<xsl:text>
<xsl:value-of select="node()" />.jpg
</xsl:text>
</xsl:attribute>
</img>
but it doesng work
Use:
<img src="{normalize-space()}.jpg"/>
This assumes the <img> element is the current node.
The reason why what you are doing does not work is that you cannot evaluate XSLT expressions inside of the <xsl:text> element.
<xsl:text> can only contain literal text, entity references, and #PCDATA.
If you move the <xsl:value-of> outside of the <xsl:text>, then the following will work:
<img>
<xsl:attribute name="src">
<xsl:value-of select="node()" />
<xsl:text>.jpg</xsl:text>
</xsl:attribute>
</img>
However, selecting <xsl:value-of select="node()> for the <img> in your example will include the carriage returns and whitespace characters inside of the <img> element, which is probably not what you want in your src attribute value.
That is why Dimitre Novatchev used normalize-space() in his answer. Applying that to the example above:
<img>
<xsl:attribute name="src">
<xsl:value-of select="normalize-space(node())" />
<xsl:text>.jpg</xsl:text>
</xsl:attribute>
</img>
If you get rid of the <xsl:text> as Fabiano's solution suggests, then you could also do this:
<img>
<xsl:attribute name="src"><xsl:value-of select="normalize-space(node())" />.jpg</xsl:attribute>
</img>
Just remove the tag xsl:text, in this case, you won't need it. Try this:
<img>
<xsl:attribute name="src">
<xsl:value-of select="concat(node(), '.jpg')"/>
</xsl:attribute>
</img>
I didn't test it, but it should work. =)
<img>
<xsl:attribute name="src">
<xsl:value-of select="my_photo/#href" />
</xsl:attribute>
</img>
<my_photo href="folder/poster.jpg" />
I have the following xsl code in an xsl document
<A target="_blank" style="text-decoration=none">
<xsl:attribute name="href">viewdoc.aspx?doc=<xsl:value-of select="URLFilePath"/>&mode=inline</xsl:attribute>
<xsl:attribute name="prefix"><xsl:value-of select="FileName"/>: </xsl:attribute>
<IMG src="images/word_small.gif" border="0"/>
</A>
and in the code-behind I am doing this
newItemNode = xmlDocument.CreateElement("URLFilePath")
newItemNode.InnerText = correctedPath
xmlItemNode.ParentNode.AppendChild(newItemNode)
Now that works fine for word documents. However I need a way in code to check the extension of the file, and display the correct Image and xsl:attribute depending on the If statement.
So the If statement will be like this:-
If correctedPath.ToLower.Contains(".doc") Then
//display the word icon and attributes
Else
//display the excel icon and attributes
End If
Can you please give me some tips and help on how I can achieve this?
Thanks
Just using contains() may generally produce the wrong results (see the test XML document).
What is necessary is a ends-with() function, which is standard in XPath 2.0 and can be implemented in XSLT 1.0 as in the following transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="URLFilePath">
<xsl:variable name="visDoc">
<xsl:call-template name="ends-with">
<xsl:with-param name="pEnding" select="'.doc'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="visXls">
<xsl:call-template name="ends-with">
<xsl:with-param name="pEnding" select="'.xls'"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$visDoc=1">word_small.gif</xsl:when>
<xsl:when test="$visXls=1">xls_small.gif</xsl:when>
<xsl:otherwise>unknown_small.gif</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="ends-with">
<xsl:param name="pEnding"/>
<xsl:value-of select=
"number(substring(.,
string-length() -string-length($pEnding) +1
)
=
$pEnding
)
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following test XML document:
<files>
<URLFilePath>myFile.doc</URLFilePath>
<URLFilePath>myFile.xls</URLFilePath>
<URLFilePath>myFile.xls.doc</URLFilePath>
<URLFilePath>myFile.doc.xls</URLFilePath>
</files>
the correct result is produced:
word_small.gif
xls_small.gif
word_small.gif
xls_small.gif
Do note that just using contains() produces incorrect results.
I managed to come up with a solution! Sorry for the late reply but had to work on something else
Here is the code:-
<A target="_blank" style="text-decoration=none">
<xsl:choose>
<xsl:when test="contains(., '.doc')">
<xsl:attribute name="href">viewdoc.aspx?doc=<xsl:value-of select="URLFilePath"/>&mode=inline
</xsl:attribute>
<xsl:attribute name="prefix">
<xsl:value-of select="FileName"/>:
</xsl:attribute>
<IMG src="images/word_small.gif" border="0"/>
</xsl:when>
<xsl:when test="contains(., '.xls')">
<xsl:attribute name="href">viewxls.aspx?doc=<xsl:value-of select="URLFilePath"/>&mode=inline
</xsl:attribute>
<xsl:attribute name="prefix">
<xsl:value-of select="FileName"/>:
</xsl:attribute>
<IMG src="images/excel_small.gif" border="0"/>
</xsl:when>
</xsl:choose>
</A>
Thanks for all your help guys, really very much appreciated!
A late reply but I hit to two answers that deal with matching end of string with XSLT 1.0 and are very elegant:
https://stackoverflow.com/a/3081205/520567
https://stackoverflow.com/a/3081866/520567
go give them +1
This can be done purely in your XSLT document if you require. For displaying the image, you could use a xsl:choose statement, that tests the URLFilePath element
<xsl:choose>
<xsl:when test="contains(., '.doc')">
<IMG src="images/word_small.gif" border="0"/>
</xsl:when>
<xsl:when test="contains(., '.xls')">
<IMG src="images/excel_small.gif" border="0"/>
</xsl:when>
</xsl:choose>
If you wanted to do this check in the code behind, you could always add extra attributes to your URLFilePath element.
imageAttr = xmlDocument.CreateAttr("image")
If correctedPath.ToLower.Contains(".doc") Then
imageAttr.value = "images/word_small.gif"
Else
imageAttr.value = "images/excel_small.gif"
End If
newItemNode.AppendChild(imageAttr)
And then, in your xls, you can simply use this attribute to set the source attribute of the image
<IMG border="0">
<xsl:attribute name="src"><xsl:value-of select='#image' /></xsl:attribute>
</IMG>
I'm using XSLT for displaying a ul menu containing li and a.
I want the following:
Find the first li a element and add the .firstitem class.
Find the last li a element and add the .lastitem class.
Find the active li a element and add the .active class.
Add an unique ID to each li a element. (I.e. URL friendly menu text as ID).
I've managed to make step 1-3 work. Except that when I try to add the classes, it actually replaces the other classes rather than adding to them.
Here's the code:
<li>
<a>
<!-- Add .firstitem class -->
<xsl:if test="position() = 1">
<xsl:attribute name="class">firstitem</xsl:attribute>
</xsl:if>
<!-- Add .lastitem class -->
<xsl:if test="postition() = count(//Page)">
<xsl:attribute name="class">lastitem</xsl:attribute>
</xsl:if>
<!-- Add .active class -->
<xsl:if test="#Active='True'">
<xsl:attribute name="class">active</xsl:attribute>
</xsl:if>
<!-- Add link URL -->
<xsl:attribute name="href"><xsl:value-of select="#FriendlyHref" disable-output-escaping="yes"/></xsl:attribute>
<!-- Add link text -->
<xsl:value-of select="#MenuText" disable-output-escaping="yes"/>
</a>
</li>
In realtity, the a element could contain all those three classes. But as is goes through the code, it replaces everything in the class attribute. How can I add the classes instead of replacing them?
And step number 4 on my list, is to get a unique ID, preferably based on #MenuText. I know there is a replace() function, but I can't get it to work and my editor says that replace() isn't a function.
The menu item text contains spaces, dashes and other symbols that are not valid for using in the id attribute. How can I replace those symbols?
<a>
<xsl:attribute name="class">
<!-- Add .firstitem class -->
<xsl:if test="position() = 1">
<xsl:text> firstitem</xsl:text>
</xsl:if>
<!-- Add .lastitem class -->
<xsl:if test="postition() = count(//Page)">
<xsl:text> lastitem</xsl:text>
</xsl:if>
<!-- Add .active class -->
<xsl:if test="#Active='True'">
<xsl:text> active</xsl:text>
</xsl:if>
</xsl:attribute>
<!-- Add link URL -->
<xsl:attribute name="href"><xsl:value-of select="#FriendlyHref" disable-output-escaping="yes"/></xsl:attribute>
<!-- Add link text -->
<xsl:value-of select="#MenuText" disable-output-escaping="yes"/>
</a>
replace() is an XSLT2.0 function. When using XSLT1.0 you need a custom template to do most string manipulations.
I'm adding this to Martijn Laarman's answer, which covers your requirements 1-3 and has my vote:
To remove everything except a certain range of characters from a string with XSLT 1.0 (your 4th requirement), do the following.
<!-- declare at top level -->
<xsl:variable
name="validRange"
select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
/>
<!-- later, within a template… -->
<xsl:attribute name="id">
<xsl:value-of select="
concat(
'id_',
translate(
#MenuText,
translate(#MenuText, $validRange, ''),
''
)
)
" />
</xsl:attribute>
The inner translate() removes any valid character from #MenuText, leaving only the invalid ones. These are fed to the outer translate(), which now can remove all invalid chars from the #MenuText, whatever they might be in this instance. Only the valid chars remain.
You can make a function out of it:
<xsl:template name="HtmlIdFromString">
<xsl:param name="input" select="''" />
<xsl:value-of select="
concat('id_', translate( $input, translate($input, $validRange, ''), ''))
" />
</xsl:template>
and call it like this:
<xsl:attribute name="id">
<xsl:call-template name="HtmlIdFromString">
<xsl:with-param name="input" select="#MenuText" />
</xsl:call-template>
</xsl:attribute>
Use
<xsl:template match="#*">
<xsl:copy>
<xsl:apply-templates select="#*"/>
</xsl:copy>
</xsl:template>
to copy all existing attributes.
The replace() function is only supported in xslt 2.0 but i found this workaround for xslt 1.0.