Is it possible to write out xml based on an "if" "Like" statement or the equivalent of in xslt?
I have an element named "cust_code"
If the element starts with a "HE" then I want to write it out, otherwise jump to the next.
Is it possible?
If statements exist in XSLT.
<xsl:if test="...">
...
</xsl:if>
But this is a simple if, with no alternative.
If you want an equivalent to if ... else ... or switch ... case ..., you need to use the following:
<xsl:choose>
<xsl:when test="...">
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
You can have as many when cases as necessary.
Links: w3school - if and w3school - choose.
As to having an element starting with a specific string, look at the function starts-with. You can find a good example in this SO answer (just omit the not from the main answer, as their tests was to find strings not starting with a particular string). You can also look at this answer for more information.
Related
Within an xsl:for-each select loop, I have <xsl:number count="//headline"/> that correctly gives me the node #; Now I want to use that number in an xsl:if test block, but I cannot get the test expression right, msxml4.dll keeps kicking back errors. Am using xsl 1.0 (and stuck with it for now)
So, in <xsl:if test="expression">...output if the expression is true..</xsl:if>
I want the test expression to essentially be like this (so I can do something specific for Node #4, in this example):
<xsl:number count="//headline"/> = 4
This is what I have that does not work:
<xsl:if test="<xsl:number count="//headline"/> = 4">
Thanks in advance for any insights,
George
As #michael.hor257k explains, the general approach is to put the xsl:number call inside an xsl:variable (or in XSLT 2.0, inside an xsl:function). Sometimes though it's more convenient to abandon xsl:number:
<xsl:if test="count(preceding::headline) = 3">...</xsl:if>
If it's a big document then both xsl:number and preceding::headline are potentially expensive when executed inside a loop, and if this is a concern then you should compare them under your chosen XSLT processor: one may be optimized better than the other.
Come to think of it, your use of xsl:number looks odd to me. The count attribute is a pattern, and the pattern //headline matches exactly the same nodes as the pattern headline. As a result I misread your call on xsl:number as counting all the headlines in the document, whereas it actually only counts the preceding-sibling headlines. I wonder if that is what you intended?
If (!) I understand correctly, you want to do something like:
<xsl:variable name="n">
<xsl:number count="headline"/>
</xsl:variable>
<xsl:value-of select="$n"/>
<xsl:if test="$n = 4">
<!-- do something -->
</xsl:if>
and I have some code now that says:
<xsl:choose>
<xsl:when test="$Admin = 2">
<img src="../Lists/Announcement/Attachments/1/Banner.jpg" style="height:189px; width:568px;" title="{#Title};" />
</xsl:when>
<xsl:otherwise>
<img src="../Lists/Announcement/Attachments/{#ID}/Banner.jpg" style="height:189px; width:568px;" title="{#Title};" />
</xsl:otherwise>
</xsl:choose>
I would like to compound the condition so that it will also accept an attachment called banner.png also, and show banner.png.
If I use the substring function and give it a negative number will it count backwards from the end of the string?
If I use the substring function and give it a negative number will it count backwards from the end of the string?
No. (What made you think it would? Did you actually look for a specification? Did you try it? Guessing, and asking on SO whether your guess is correct, doesn't sound like a very efficient way of getting things done.)
I know this may seem like a dumb/newbie question, but I'm fairly new to XSLT (though I'm starting to come around to it and see it's capabilities).
When is it appropriate to use xsl:if and when is it appropriate to use xsl:choose/xsl:when?
I have been using choose/when/otherwise when I want to have an "else" option. Is this correct?
For instance I have some places where I'm doing:
<xsl:choose>
<xsl:when test="count(entry) != 0">
put positive outcome here
</xsl:when>
<xsl:otherwise>
put something else here
</xsl:otherwise>
</xsl:choose>
would xsl:if be better?
Thanks for the input.
Use xsl:if for simple cases where you just want to test if an expression is true. (Note that there is no corresponding xsl:else.)
<xsl:if test="expression">
output if the expression is true
</xsl:if>
Use xsl:choose for cases where you have some alternate output when the expressions is false.
<xsl:choose>
<xsl:when test="expression">
output if the expression is true
</xsl:when>
<xsl:otherwise>
output if the expression is false
</xsl:otherwise>
</xsl:choose>
would xsl:if be better?
Not really - unless you want to have two xsl:ifs and ensure that their conditions are mutually exclusive.
an xsl:choose will always select exactly one of the available xsl:when or xsl:otherwise
The <xsl:when> children of the <xsl:choose> element are tested, in order from top to bottom, until a test attribute on one of these elements accurately describes conditions in the source data, or until an <xsl:otherwise> element is reached. Once an <xsl:when> or <xsl:otherwise> element is chosen, the <xsl:choose> block is exited. No explicit break or exit statement is required.
It's remarkably similar to a switch statement from C inspired languages (C, C++, Java, C#) or Select...Case from Visual Basic
The xsl:if doesn't have the equivalent from such languages of an else clause, so I'd only recommend it if you want to either do "something" or not (I.e. in the not case, you don't want to specify an alternative)
I have the following element as part of a larger XML
<MT N="NonEnglishAbstract" V="[DE] Deutsch Abstract text [FR] French Abstract text"/>
I need to do some formatting of the value in #V attribute, only if it contains anything like [DE], [FR] or any two capital letters representing a country code within square brackets.
If no such pattern exist, I need to simply write the value of #V without any formatting.
I can use an XSLT 2.0 solution
I was hoping that I could use the matches() function something like
<xsl:choose>
<xsl:when test="matches(#V,'\[([A-Z]{{2}})\]([^\[]+'">
//Do something
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#V"/>
</xsl:otherwise>
</xsl:choose>
I think all you need is:
matches(#V,'\[[A-Z][A-Z]\]')
You don't have to match the entire string to get a true() ... I tell my students to write as short a reg-ex as possible.
You have not posted anything about what you have tried. How about looking up translate function and translating the strings capital letters to something like "X". Then test that string result for the existence of [XX]. That alone would tell you whether you need to process it.
<xsl:variable name="result">
<xsl:value-of select="translate(#V,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','XXXXXXXXXXXXXXXXXXXXXXXXX')"/>
</xsl:variable>
Then use that result and then test:
contains($result, "[XX]")
No regex required, pure XSL 1.1
I am new to xslt and I am wondering whether it is possible to compare the value of "#userNameKey" and the value of
<xsl:value-of select="./text()"/> in example below?
<xsl:if test="#userNameKey='??????'">
<xsl:attribute name="selected">true</xsl:attribute>
</xsl:if>
<xsl:value-of select="./text()"/>
Basically, I just want to replace the questionmarks with the following fragment: <xsl:value-of select="./text()"/> but there is an issue with the double quotes. Should I use escape characters (if yes, what are they?) or there is a better solution?
If you specifically want to compare against the value of the first text node child of the current element (which is what <xsl:value-of select="./text()"/> gives you), then use
<xsl:if test="#userNameKey=string(text())">
At first sight
<xsl:if test="#userNameKey=text()">
may seem more obvious, but this is subtly different, returning true if the userNameKey matches any one of the text node children of the current element (not necessarily the first one).
But if (as I suspect you really mean) you want to compare the userNameKey against the complete string value of the element even if that consists of more than one text node, then use
<xsl:if test="#userNameKey=.">
Remember that text() is a node set containing all the text node children of the context node, and if you're not sure you need to use it (e.g. when you want to process each separate text node individually) then you probably don't.
You should be able to do just this...
<xsl:if test="#userNameKey=./text()">
<xsl:attribute name="selected">true</xsl:attribute>
</xsl:if>
In fact, the ./ is not needed here, so you can just do this
<xsl:if test="#userNameKey=text()">
<xsl:attribute name="selected">true</xsl:attribute>
</xsl:if>