I'm trying to preserve row breaks in an xml file when transforming it to html, but I cant find a way that works.
<meta>
<name>Message</name>
<value>Hi!
I need info!
Mr Test</value>
</meta>
And I use this xsl:
<xsl:if test="name='Message'">
<tr>
<th align="left" colspan="2">Message:</th>
</tr>
<tr>
<td colspan="2"><xsl:value-of select="value"/></td>
</tr>
</xsl:if>
But the new line (cr/lf) characters dissapear, and everything becomes one single line in html. Is is possible to match the cr/lf and replace them with html "<_br >", or any other method?
Add the following template to your XSL:-
<xsl:template name="LFsToBRs">
<xsl:param name="input" />
<xsl:choose>
<xsl:when test="contains($input, '
')">
<xsl:value-of select="substring-before($input, '
')" /><br />
<xsl:call-template name="LFsToBRs">
<xsl:with-param name="input" select="substring-after($input, '
')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$input" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Now replace where select the value with a call to this template:-
<td colspan="2">
<xsl:call-template name="LFsToBRs">
<xsl:with-param name="input" select="value"/>
</xsl:call-template>
</td>
Greetings, if you already have LF or CR in the source xml (looks like you have),
try putting in a with "white-space: pre" style.
i.e:
<div style="white-space: pre;">
<xsl:value-of select="value"/>
</div>
Related
The input is an XML file
<test-results name="project name" total="73" errors="0" failures="43" not-run="0" inconclusive="0" ignored="0" skipped="0" invalid="0" date="2016-01-05" time="20:32:22">
.......
</test-results>
I want to calculate the "No of pass results" and "Pass Percentage". I have done with the No of pass results. It is working fine
<tr>
<td>Number of Passes</td>
<td>
<xsl:variable name="failures" select="#failures"/>
<xsl:variable name="total" select="#total"/>
<xsl:choose>
<xsl:when test="$failures != ''">
<xsl:value-of select="($total - $failures)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#total"/>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
Now I want to calculate the pass percentage(eg :- 87.45%). I tried the below logic. but it is throwing an exception
<tr>
<td>Success Rate</td>
<td>
<xsl:variable name="Pass" select="#total - #failures"/>
<xsl:variable name="totalNo" select="#total"/>
<xsl:value-of select="($Pass/$totalNo)*100"/>
</td>
</tr>
Can anyone help me out to calculate the pass percentage?
Thanks in advance.
Use the div operator instead of the / sign:
<xsl:value-of select="$Pass div $totalNo * 100"/>
I have a node like this in an XML file that I transform with XSLT 2.0:
<h2><span class='sun'>☼☼</span> my text (G1.2)</h2>
which includes some HTML special characters, as you see.
Now I need to generate XHTML like this:
my text
So I have to strip out the span and the stuff between () and use the rest to generate the h2 header.
To strip the (), I have this:
<xsl:value-of select="normalize-space(replace( . ,'\([^\)]*\)' ,''))"/>
which works OK. But to strip the span, I cannot use
<xsl:template match="span[#class='sun']"/>
Because I do not apply templates after the xsl:value-of anymore. So the span-template is never applied.
Can I strip the span in the same line? If not, how can I strip the span also?
Or can I replace the special characters in the same replace function somehow? Then I would be left with an empty span element, but that's not a problem.
You can match the child::text() contents of <h1> separately from the child::span elements. This should work:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="span[#class='sun']"/>
<xsl:template match="h2/text()">
<a href="">
<xsl:value-of select="normalize-space(replace( . ,'\([^\)]*\)' ,''))"/>
</a>
</xsl:template>
</xsl:stylesheet>
Here is the template thus far. It (toct) generates a table of contents from a HTML h1/h2/h3 structure recursively.
It is applied like this:
<xsl:call-template name="toct">
<xsl:with-param name="nodes" select="document(file)//(h1|h2|h3)"/>
<xsl:with-param name="file" select="replace (file,'xml', 'xhtml')"/>
</xsl:call-template>
<xsl:template name="toct">
<xsl:param name="nodes"/>
<xsl:param name="file"/>
<xsl:if test="count($nodes) > 0">
<xsl:for-each-group select="$nodes" group-starting-with="*[local-name() = name($nodes[1])]">
<li>
<!-- do not include empty header tags in the TOC -->
<a>
<xsl:choose>
<xsl:when test="text()">
<xsl:if test="name($nodes[1])='h1'">
<xsl:attribute name="id"><xsl:value-of select="$nodes[1]/#id"/></xsl:attribute>
</xsl:if>
<xsl:attribute name="href"><xsl:value-of select="$file"/>#<xsl:value-of select="#id"/></xsl:attribute>
<xsl:value-of select="normalize-space(replace(replace( string-join(node(),'') , '[☼*]' ,'') ,'\([^\)]*\)' ,''))"/>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class">invisible</xsl:attribute>
<xsl:text>-</xsl:text>
</xsl:otherwise>
</xsl:choose>
</a>
<xsl:if test="current-group()[2]">
<ol>
<xsl:call-template name="toct">
<!-- strip the first node in the list. This is why you can use $nodes[1] to find out
which level of <h_> tags you are at -->
<xsl:with-param name="nodes" select="current-group() except ."/>
<xsl:with-param name="file" select="$file"/>
</xsl:call-template>
</ol>
</xsl:if>
</li>
</xsl:for-each-group>
</xsl:if>
</xsl:template>
Typically i am doing an XSLT process over a Weblogic12 server. I kept running into this issue
net.sf.saxon.trans.DynamicError: An attribute node
(id) cannot be created after the children of the containing element
Before the migration, our team had no problems at all...
Any idea why? i recently upgraded from BEA Weblogic3 to Oracle Enterprise Weblogic 12. Or am i missing a library?
This is plaguing our entire team! Thanks!
EDIT 1:
Error points to <xsl:attribute name="id"> in <xsl:template name="makeErrorDiv">
<td>
<xsl:copy-of select="#colspan | #align | #style | #valign | #class | #id | #name"/>
<xsl:if test="#colspan = '1' and $columnWidth != '' and not(#suppressColWidth='true')"><xsl:attribute name="width"><xsl:value-of select="$columnWidth"/></xsl:attribute></xsl:if>
<xsl:if test="#rowspan != '1'"><xsl:copy-of select="#rowspan"/></xsl:if>
<xsl:if test="descendant::ErrMsg">
<xsl:call-template name="makeErrorDiv"/>
</xsl:if>
</td>
<xsl:template name="makeErrorDiv">
<div style="display:none;">
<xsl:choose>
<xsl:when test="descendant::*[ParentId]">
<xsl:attribute name="id"><xsl:value-of select="descendant::ParentId[position() = 1]"/><![CDATA[$err]]></xsl:attribute>
</xsl:when>
<xsl:when test="descendant::*[ErrMsg][Name]">
<xsl:attribute name="id"><xsl:value-of select="descendant::*[ErrMsg][position() = 1]/Name"/><![CDATA[$err]]></xsl:attribute>
</xsl:when>
<xsl:when test="not(descendant::*[ErrMsg])">
<xsl:variable name="name"><xsl:value-of select="descendant::*[Name][position() = 1]/Name"/></xsl:variable>
<xsl:variable name="parsed"><xsl:value-of select="substring-before($name, '!')"/></xsl:variable>
<xsl:attribute name="id"><!--error here! -->
<xsl:choose>
<xsl:when test="$parsed = ''"><xsl:value-of select="$name"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$parsed"/></xsl:otherwise>
</xsl:choose>
<xsl:text><![CDATA[$err]]></xsl:text></xsl:attribute>
</xsl:when>
<xsl:when test="descendant::*[ErrMsg][not(Name)]">
<xsl:variable name="name"><xsl:value-of select="descendant::*[Name][position() = 1]/Name"/></xsl:variable>
<xsl:variable name="parsed"><xsl:value-of select="substring-before($name, '!')"/></xsl:variable>
<xsl:attribute name="id">
<xsl:choose>
<xsl:when test="$parsed = ''"><xsl:value-of select="$name"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$parsed"/></xsl:otherwise>
</xsl:choose>
<xsl:text><![CDATA[$err]]></xsl:text></xsl:attribute>
</xsl:when>
</xsl:choose>
<span style="color: #FF0000; font-family: Arial, Helvetica, sans-serif; font-size: 10px; font-weight: bold; text-decoration: none;"><xsl:value-of select="descendant::ErrMsg[position() = 1]"/></span>
</div>
</xsl:template>
XML sample...not sure if it's helpful...the entire XML file is 1000+ lines
<DisclosureRowColor template="OneColumn" position="8" lastPosition="30" colCount="4" color1="#F2F8FE" color2="#ffffff">
<Cell colspan="1">
<ListBox onchange="toggleAddressByAjax();">
<Name>APPLICATION_CUSTOMER.EMPLOYED_SINCE_MM!YLI</Name>
<Size>1</Size>
<Default rtexprvalue="true">mb.getValue("APPLICATION_CUSTOMER.EMPLOYED_SINCE_MM!YLI", "A")</Default>
<Map rtexprvalue="true">mb.getGenericLookup("V_YEAR")</Map>
<ReadOnly rtexprvalue="true">mb.isReadonly(2)</ReadOnly>
</ListBox>
<Label class="sTGBFBS">
<Caption> Jahre </Caption>
</Label>
<ListBox onchange="toggleAddressByAjax();">
<Name>APPLICATION_CUSTOMER.EMPLOYED_SINCE_MM!MLI</Name>
<Size>1</Size>
<Default rtexprvalue="true">mb.getValue("APPLICATION_CUSTOMER.EMPLOYED_SINCE_MM!MLI", "A")</Default>
<Map rtexprvalue="true">mb.getGenericLookup("V_MONTH")</Map>
<ReadOnly rtexprvalue="true">mb.isReadonly(2)</ReadOnly>
</ListBox>
<Label class="sTGBGBS">
<Caption> Monate </Caption>
</Label>
<ErrMsg/>
</Cell>
</DisclosureRowColor>
I think your problem might be the <xsl:text> nodes inside of your <xsl:attribute> element
<xsl:text><![CDATA[$err]]></xsl:text></xsl:attribute>
I think that should just say
<![CDATA[$err]]></xsl:attribute>
since you're creating an attribute, not a text node.
Update:
I tried to reproduce the error, but couldn't. BUT, I did find that saxon was using whitespace in the attribute. You might want to try Getting rid of some of the whitespace between some of the XSL elements.
<xsl:when test="not(descendant::*[ErrMsg])">
<xsl:variable name="name"><xsl:value-of select="descendant::*[Name][position() = 1]/Name"/></xsl:variable>
<xsl:variable name="parsed"><xsl:value-of select="substring-before($name, '!')"/></xsl:variable>
<xsl:attribute name="id"><xsl:choose>
<xsl:when test="$parsed = ''"><xsl:value-of select="$name"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$parsed"/></xsl:otherwise>
</xsl:choose><xsl:text><![CDATA[$err]]></xsl:text></xsl:attribute>
</xsl:when>
And this might solve your the actual error you're seeing:
<div style="display:none;"><xsl:choose>
I think some text must be getting added to your 'div' element before the id attribute can be added.
I have this xslt which is working:
<xsl:when test="area_of_expertise">
<div>
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
but what i need is along the lines of:
<xsl:when test="area_of_expertise">
<div id="<xsl:value-of select="area_of_expertise"/>">
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
However the second example has errors.. does anyone know why?
Btw Is there a way we can transform the node's name area_of_expertise into areaOfExperiseLabel and insert that as the id? the output that i really need is this:
<div id="areaOfExpertiseLabel">
asasdasdasd
</div>
The reason it errors out is because it's no longer valid XML.
To do what you're trying to do:
<xsl:when test="title">
<div id="{title}">
<xsl:value-of select="title"/>
</div>
</xsl:when>
You can put any sort of selector inside of the {} tags, or even reference variables if you have something complex.
<xsl:variable name="some_complex_variable">
<xsl:value-of select="title"/>
</xsl:variable>
<xsl:when test="title">
<div id="{$some_complex_variable}">
<xsl:value-of select="title"/>
</div>
</xsl:when>
A 3rd, long-winded way of doing it is to dynamically attach the attribute with xsl:attribute:
<xsl:when test="title">
<div>
<xsl:attribute name="id" select="title"/>
</div>
</xsl:when>
For 2nd part try using this template:
<xsl:template name="parse">
<xsl:param name="input"/>
<xsl:param name="position"/>
<xsl:if test="$position <= string-length($input)">
<xsl:choose>
<xsl:when test="substring($input, $position, 1) = '_'">
<xsl:value-of select="translate(substring($input, $position + 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
<xsl:call-template name="parse">
<xsl:with-param name="input" select="$input"/>
<xsl:with-param name="position" select="$position + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($input, $position, 1)"/>
<xsl:call-template name="parse">
<xsl:with-param name="input" select="$input"/>
<xsl:with-param name="position" select="$position + 1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
Usage:
<xsl:call-template name="parse">
<xsl:with-param name="input" select="'area_of_expertise'"/>
<xsl:with-param name="position" select="1"/>
</xsl:call-template>
For the second part, converting from underscores to camel case, you may want to look at String Processing in the XSLT Standard Library. With str:subst() to split at underscores, str:to-camelcase() to change letter case suitably, and concat() to add the "Label" suffix, you should be set.
For the 1st part you could use:
<xsl:when test="area_of_expertise">
<div>
<xsl:attribute name="id">
<xsl:value-of select="area_of_expertise"/>
</xsl:attribute>
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
It might be a silly answer, but it seems that you need this simple trace:
<xsl:when test="area_of_expertise">
<div id="areaOfExperiseLabel">
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
Otherwise, why are you intersted in <xsl:value-of select="area_of_expertise"/> for #id if you then need another string?
In a program im writing, parts of the web interface are sent to the client as XML, and transformed into HTML fragments using Javascript and an XSLT. This works fine in Firefox (4.0b12) and Opera (10.63) but in Chrome (9.0.597.107) the results arn't as expected.
The XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent ="yes"/>
<xsl:template match ="/">
<xsl:for-each select="queue/download">
<xsl:choose>
<xsl:when test="status='downloadError'">
<xsl:variable name="rowClass">ui-state-error</xsl:variable>
<xsl:variable name="iconClass">ui-icon ui-icon-alert</xsl:variable>
<xsl:call-template name="download">
<xsl:with-param name="iconClass" select="$iconClass"/>
<xsl:with-param name="rowClass" select ="$rowClass"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="status='downloadRunning'">
<xsl:variable name="rowClass">ui-state-highlight</xsl:variable>
<xsl:variable name="iconClass">ui-icon ui-icon-refresh</xsl:variable>
<xsl:call-template name="download">
<xsl:with-param name="iconClass" select="$iconClass"/>
<xsl:with-param name="rowClass" select ="$rowClass"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="status='downloadComplete'">
<xsl:variable name="rowClass">downloadComplete</xsl:variable>
<xsl:variable name="iconClass">ui-icon ui-icon-circle-check</xsl:variable>
<xsl:call-template name="download">
<xsl:with-param name="iconClass" select="$iconClass"/>
<xsl:with-param name="rowClass" select ="$rowClass"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="rowClass" select ="status" />
<xsl:variable name="iconClass"/>
<xsl:call-template name="download">
<xsl:with-param name="iconClass" select="$iconClass"/>
<xsl:with-param name="rowClass" select ="$rowClass"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="download">
<xsl:param name="rowClass"/>
<xsl:param name="iconClass" />
<xsl:variable name="id" select ="id"/>
<xsl:variable name="filename" select ="filename"/>
<xsl:variable name="comment" select ="comment"/>
<tr class="{$rowClass}">
<td class="downloadCheck">
<input type="checkbox" class="downloadCheckbox" value="{$id}" name="downloadCheckbox"/>
</td>
<td class="downloadIcon">
<span class="{$iconClass}"></span>
</td>
<td class="downloadName">
<a href="#" onclick="showDownloadCommentBox('{$id}','{$filename}', '{$comment}');">
<xsl:value-of select="filename"/>
</a>
</td>
<xsl:if test="status='downloadError'">
<td class="dError" colspan="4">
<xsl:value-of select ="errortext"/>
</td>
</xsl:if>
<xsl:if test ="status!='downloadError'">
<xsl:variable name="progress" select ="progress"/>
<td class="downloadProgress">
<div class="jqProgress" value="{$progress}"></div>
</td>
<td class="downloadTimeLeft">
<xsl:value-of select ="timeremaining"/>
</td>
<td class="downloadSize">
<xsl:value-of select ="size"/>
</td>
<td class="downloadSpeed">
<xsl:value-of select ="speed"/>
</td>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>
The XML
<queue>
<name>test</name>
<renderer>downloadQueue</renderer>
<xsl>/xslt/downloadQueue.xslt</xsl>
<status>suspended</status>
<startMode>manual</startMode>
<downloadDirectory>C:\Users\William\Programming\SCRAMDownloader\Trunk\bin\</downloadDirectory>
<download>
<filename>test.zip</filename>
<progress>0.00%</progress>
<speed>-</speed>
<timeremaining>-</timeremaining>
<status>downloadSuspended</status>
<size>119.68 MB</size>
<id>8976170e-1f4b-4b79-8901-5a4191e2c07d</id>
<comment/>
</download>
</queue>
Expected Results (Firefox)
<tr class="downloadSuspended">
<td class="downloadCheck"><input type="checkbox" class="downloadCheckbox" value="8976170e-1f4b-4b79-8901-5a4191e2c07d" name="downloadCheckbox"></td>
<td class="downloadIcon"><span class=""></span></td>
<td class="downloadName">test.zip</td>
<td class="downloadProgress"><div class="jqProgress ui-progressbar ui-widget ui-widget-content ui-corner-all" value="0.00%" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="ui-progressbar-value ui-widget-header ui-corner-left" style="width: 0%;"></div></div></td>
<td class="downloadTimeLeft">-</td>
<td class="downloadSize">119.68 MB</td>
<td class="downloadSpeed">-</td>
</tr>
Results in Chrome
<input type="checkbox" class="downloadCheckbox" value="8976170e-1f4b-4b79-8901-5a4191e2c07d" name="downloadCheckbox">
<span class=""></span>
test.zip
<div class="jqProgress ui-progressbar ui-widget ui-widget-content ui-corner-all" value="0.00%" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="ui-progressbar-value ui-widget-header ui-corner-left" style="width: 0%; "></div></div>
-
119.68 MB
-
Note the missing <tr> and <td> tags
Any ideas what im doing wrong?
(Apologies for the overly long post)
Any ideas what im doing wrong?
Nothing, except perhaps using a buggy XSLT processor (whatever google-chrome uses).
I have tested this transformation with the following nine different XSLT (1.0 and 2.0) processors and the result from all of them is correct:
MSXML 3,4,6
ALtova (XML SPY)
.NET (XslCompiledTransform and XslTransform)
Saxon (6.5.4 and 9.1.05)
XQSharp
I just had the same issue.
I gues the problem is that chrome validates the output of the xslt parsing and expects a surrounding the and . If you put around your 's, I think the problem would be solved (it works for me...)
You can then strip the tag from the result if you don't need it...