Facing issues in parsing xml with xslt - html

I am trying to parse a xml to generate a html report.The problematic section of the xml is as given
<failure message="Management changes link count is not 3$HiHello" type="junit.framework.AssertionFailedError">junit.framework.AssertionFailedError: Management changes link count is not 3$HiHelloJI
at CustomProjects.CommonTemplates.verifyManagementChanges(Unknown Source)
at CustomProjects.EmersonTest.testEmerson_VerifyManagementChanges(Unknown Source)
</failure>
The xslt written for parsing this is :
<xsl:choose>
<xsl:when test="failure">
<td>Failure</td>
<td><xsl:apply-templates select="failure"/></td>
<td>screenshot</td>
<td><xsl:apply-templates select="failurelink"/></td>
</xsl:when>
</xsl:choose>
<xsl:template match="failure">
<xsl:call-template name="display-failures"/>
</xsl:template>
<xsl:template match="failurelink">
<xsl:call-template name="display-failures-link"/>
</xsl:template>
<xsl:template name="display-failures">
<xsl:param name="FailText" select="#message"/>
<xsl:choose>
<xsl:when test="not(#message)">N/A</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($FailText,'$')"/>
</xsl:otherwise>
</xsl:choose>
<!-- display the stacktrace -->
<code>
<br/><br/>
<xsl:call-template name="br-replace">
<xsl:with-param name="word" select="."/>
</xsl:call-template>
</code>
<!-- the later is better but might be problematic for non-21" monitors... -->
<!--pre><xsl:value-of select="."/></pre-->
</xsl:template>
<xsl:template name="display-failures-link">
<xsl:param name="linktext" select="#message"/>
<xsl:choose>
<xsl:when test="not(#message)">N/A</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-after($linktext,'$')"/>
</xsl:otherwise>
</xsl:choose>
<!-- display the stacktrace -->
<code>
<br/><br/>
<xsl:call-template name="br-replace">
<xsl:with-param name="word" select="."/>
</xsl:call-template>
</code>
<!-- the later is better but might be problematic for non-21" monitors... -->
<!--pre><xsl:value-of select="."/></pre-->
</xsl:template>
Here I am getting the desired result(The String before $ sign) from display-failures template but on calling display-failures-link I am getting nothing.(Should get the string after $ sign).I dont know whether the problem is with sunstring function or with something else.Kindly let me know what I am doing wrong here.
Any help is highly appreciated.

The problem here is that you are trying to apply-templates on the XPath failurelink, but you don't have an element called <failurelink>, so this apply-templates isn't finding anything.
<xsl:apply-templates select="failurelink"/>
One way to apply two different templates on the same kind of element is to use modes:
<xsl:template match="failure">
<xsl:call-template name="display-failures"/>
</xsl:template>
<xsl:template match="failure" mode="link">
<xsl:call-template name="display-failures-link"/>
</xsl:template>
Then the area where you apply the templates would change to this:
<td>Failure</td>
<td><xsl:apply-templates select="failure"/></td>
<td>screenshot</td>
<td><xsl:apply-templates select="failure" mode="link"/></td>
But in your case, there's an even better approach. Just eliminate the second template, and do this:
Replace the whole <xsl:choose> with:
<xsl:apply-templates select="failure" />
Replace the first template you listed with:
<xsl:template match="failure">
<td>Failure</td>
<td><xsl:call-template name="display-failures"/></td>
<td>screenshot</td>
<td><xsl:call-template name="display-failures-link"/></td>
</xsl:template>
And delete the second template you listed.

Related

Using XSL, I need to check links' href value and change if necessary while leaving other attributes alone

The following code does the following:
Finds links
Checks to see if it's a fully pathed link or an email link
If yes, it does nothing.
If no, it checks for a # to see if it's an anchor
If yes, it does nothing.
If no, it concatenates the domain in front.
This works, but if I add another attribute to the link, it strips it out as well. For example: My link
How do I keep the behavior below but also keep the style attribute?
<xsl:template match="a[#href][not(contains(#href, 'http')) and not(contains(#href, 'mailto'))]">
<xsl:choose>
<xsl:when test="starts-with(#href, '#')">
<a href="{#href}" ><xsl:value-of select="." /></a>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I am guessing (!) you want to do something like:
<xsl:template match="a[#href][not(contains(#href, 'http')) and not(contains(#href, 'mailto'))]">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:attribute name="href">
<xsl:if test="not(starts-with(#href, '#'))">
<xsl:value-of select="$domain" />
</xsl:if>
<xsl:value-of select="#href"/>
</xsl:attribute>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
Or possibly just:
<xsl:template match="a/#href[not(contains(., 'http') or contains(., 'mailto') or starts-with(., '#'))]">
<xsl:attribute name="href">
<xsl:value-of select="$domain" />
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
Untested, because no example was provided.

Changing nodes in XSLT based on context

I have one XSL file that I wanna include or use in two different contexts. In one of the contexts I want to use 'fo:block' but in the other context I want to use 'div class="Block"'.
Is there someway to change all my 'fo:block' in my XSL to 'div class="Block"' or vice versa based on the context, maybe with the use of parameters?
Its a simple condition:
<xsl:variable name="outputformat" select="'html'"/>
<xsl:choose>
<xsl:when test="$outputformat = 'html'">
<div class="Block">
<!-- your html code -->
</div>
</xsl:when>
<xsl:otherwise>
<fo:block>
<!-- your normal code -->
</fo:block>
</xsl:otherwise>
</xsl:choose>
Alternatively you can make a second xsl document and copy every node except the
<fo:block/>
which you should change to
<div class="block"/>
This would look like:
<xsl:template match="#*|node()">
<xsl:choose>
<xsl:when test="local-name() = 'block'">
<xsl:element name="div">
<xsl:attribute name="class" select="'Block'"/>
<xsl:apply-templates select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Add Space Before a tag if it is Present in XSLT

Iam creating styles using XSLT for my XML file.
Here is my code:
<xsl:template match="LEXVAR">
<xsl:copy>
<xsl:apply-templates/>
<xsl:choose>
<xsl:when test="./preceding-sibling::LEXVAR">
<span class="neutral">
<xsl:text>, </xsl:text>
</span>
</xsl:when>
<xsl:when test="./preceding-sibling::*">
<span class="neutral">
<xsl:text> </xsl:text>
</span>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:copy>
</xsl:template>
In my case: LEXVAR is tag and it is to be styled, the condition for styling is add a space if any other tag is present before to it or no space is needed.
And the above code is not working, iam new to XSl, can you please help me.?
Thanks in advance.
Try this to solve your issue :
<xsl:template match="LEXVAR">
<span class="exp">
<xsl:if test="./preceding-sibling::*">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:text></xsl:text>
<xsl:apply-templates/>
</span>
I would put the condition into a predicate of the match pattern e.g.
<xsl:template match="LEXVAR[preceding-sibling::*]">
<span><xsl:text> </xsl:text></span>
<xsl:next-match/>
</xsl:template>
Then make sure you have an identity transformation template or other template handing other LEXVAR elements so that the next-match has some template to call.

XSLT transformation for multiple font types

I am trying to make an XSLT transformation from XML, I want to transform font style tags into HTML tags, but my I am doing something wrong.
My XML file is like this one :
<root>
<p>
<span>
<i/>
italic
</span>
<span>
<i/>
<b/>
bold-italic
</span>
<span>
normal
</span>
</p>
</root>
What I want is HTML with the same tags but my XSLT transformation does not work:
HTML:
<p>
<i>italic</i>
<i><b>bold-italic</b></i>
normal
<p>
I was trying xsl:if condition but it does not work,i do not know what I am doing wrong:
XSLT:
<xsl:template match="p">
<p>
<xsl:for-each select="span">
<xsl:if test="i">
<i>
<xsl:value-of select="."/>
</i>
</xsl:if>
<xsl:if test="b">
<b>
<xsl:value-of select="."/>
</b>
</xsl:if>
</xsl:for-each>
</p>
</xsl:template>
Do you know how to repair my code ?
Can you have more than just b and i elements? It may be possible to do this with a generic solution, that creates a nested element for each child element of a span element.
This solution uses a recursive template, that matches span, but with a parameter contain the index number of the child element that needs to be output. When this index exceeds the number of child elements, the text is output.
Try this XSLT too:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="span">
<xsl:param name="num" select="1"/>
<xsl:variable name="childElement" select="*[$num]"/>
<xsl:choose>
<xsl:when test="$childElement">
<xsl:element name="{local-name($childElement)}">
<xsl:apply-templates select=".">
<xsl:with-param name="num" select="$num + 1"/>
</xsl:apply-templates>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This does assume that all the span element only contain elements you want to nest, in addition to the text.
You can test the contents of span element using an XPath expression with a predicate which tests for its contents, and match different templates for each situation. Since you need b and i for bold-italic, you should use that expression in one of your predicates.
The stylesheet below does the transformation using only templates (without the need of a for-each). I'm assuming the contents of your <span> elements is text (not mixed content):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="p">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="span[i]">
<i><xsl:value-of select="."/></i>
</xsl:template>
<xsl:template match="span[b]">
<b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="span[i and b]">
<i><b><xsl:value-of select="."/></b></i>
</xsl:template>
</xsl:stylesheet>

Tiny mce is adding extra p tags when copied from outlook or word

I think my earlier question was too large, I am trying to put some minimal content.
Problem:
When I am trying to copy some content from word/outlook to tinymce, any text after bullet points/numbers is getting discarded when writing to word.
Example:
When I copy below contnet, I am not seeing Bullet1 and Bullet2 in final word document
Word bullets test IE
• Bullet1
• Bullet2
My xslt code:
<xsl:template match="qnap:li">
<xsl:variable name="paraStyle" as="xs:string">
<xsl:choose>
<xsl:when test="parent::qnap:ol">AnswerNumbered</xsl:when>
<xsl:otherwise>AnswerBullet</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="not(qnap:p)">
<xsl:variable name="paraContent" as="element()">
<span>
<xsl:apply-templates/>
</span>
</xsl:variable>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="paraContent" as="element()">
<span>
<xsl:apply-templates select="qnap:p"/>
</span>
</xsl:variable>
</xsl:otherwise>
</xsl:choose>
Hope this is not creating any confusion. Any help would be much appreciated