XSLT is adding additional characters to HTML image elements - html

So I am creating a webpage from an XML file that I created. It is a list of all cards and their attributes from Hearthstone.
When it comes to images can someone explain why my xsl transformation is adding character data to the begging and end of my img content output? It does this even when I use a local image. I am using jEdit.
XML:
<Image_URL>
<regular>
http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/thumb/3/37/Abomination%28597%29.png/184px-Abomination%28597%29.png?version=9e47af5b792479ac6617cb30bf7da8a4
</regular>
<gold>
http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/thumb/1/10/Abomination%28597%29_Gold.png/184px-Abomination%28597%29_Gold.png?version=a340c375a36e6c10eec4a747a3170901
</gold>
</Image_URL>
XSL:
<xsl:template match="regular">
<p>
<img src="{.}"/>
</p>
</xsl:template>
Output:
<img src="%0A%09%09%09http://hydra-media.cursecdn.com/hearthstone.gamepedia.com/thumb/3/37/Abomination%28597%29.png/184px-Abomination%28597%29.png?version=9e47af5b792479ac6617cb30bf7da8a4%0A%09%09%09"></p>

You are seeing the additional whitespace surrounding the URL data, given that the element is pretty-printed.
Use normalize-space in the attribute value template to remove this:
<xsl:template match="regular">
<p>
<img src="{normalize-space(.)}"/>
</p>
</xsl:template>

Related

Import HTML Drupal module with custom XSL template

I have a requirement to import a html website to Drupal and I have decided to using Import HTML module to do it.
I have to be able to grab just the text from html page (inside tag) without the html tags.
For this, I'm trying to create a custom xsl template based on the default template: html2simplehtml.xsl.
Currently my import is working fine with html2simplehtml.xsl template.
here is example of the result node body from the import:
<div class="container-narrow">
<div class="masthead">
<ul class="nav nav-pills pull-right">
<li class="active">
Home
</li>
<li>
Applications
</li>
<li>
Middleware
</li>
now, the requirement is to only get:
Home
Applications
Middleware
I have found this to remove html tags:
<!-- This will remove the tag -->
<xsl:template name="remove-html">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '<')">
<xsl:value-of select="substring-before($text, '<')"/>
<xsl:call-template name="remove-html">
<xsl:with-param name="text" select="substring-after($text, '>')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
but I am not sure where to put and how to call it using this:
<!-- Calling the template that removes tag -->
<xsl:call-template name="remove-html">
<xsl:with-param name="text" select="{HtmlBody}"/>
</xsl:call-template>
How can I do this?
I'm not quite familiar with the way that Drupal calls your XSLT but let's assume it's a simple XSLT 1.0 processor using some HTML page as input and generating the output that you showed above. Let's further assume that the original HTML is well formed with all required closing tags, so that it's in fact XHTML which can be processed by the XSLT processor. (This is not true for the HTML you included in your question, by the way.)
So what you want to do is basically prevent all tags in the XML/XHTML input from showing up in the output. I think the easiest way to achieve this to use the <xsl:value-of select> tag. Assuming that you copy all the child tags of the <body></body> section of your XHTML like this:
<xsl:template match="body">
<xsl:copy-of select="*">
</xsl:template>
instead you could do this:
<xsl:template match="body">
<xsl:value-of select=".">
</xsl:template>
<xsl:value-of> forces the evaluation of the XML sub tree into a string which is done (simply put) by concatenating all contained text elements. This does not, however, take care of white space yet. If you want to the eliminate disturbing white space you could brace the call like this:
<xsl:template match="body">
<xsl:value-of select="normalize-space(.)">
</xsl:template>
Now for the template you originally wanted to use: This does in fact remove tags from the input, too. But if I interpret the code right the input is NOT an XML node set but it must already be a STRING. So this works for other context in which you have a literal XML representation in a string. If you tried to use it here you would have to explicitly convert your XML representation into a string beforehand by using e.g. <xsl:value-of>. In this case the template would already be stripped off the tags (as described above) and would effectively not do anything at all but return the same string that it was passed as parameter. So IMHO, you will not need this template at all.

In HTML code use another data tag in href=Variable

<!-- Section: /report/detail -->
<xsl:template match="/report/detail">
<div href="./lf_web" style="left: 0.0ex; position: absolute"><xsl:value-of select="./lf_po"/></div>
<br/>
</xsl:template>
In this code I am trying to use the content of the taq element "./lf_web".
Can any one help me please.
It is in and .xsl file and linked to .xml data source
You should tag your question with XSL instead of div and href which are not important to your question.
One way is to first retrieve the value in a variable. I like that way because you can use functions:
<xsl:variable name="website_uri" as="xs:string">
<xsl:value-of select="info/uri"/>
</xsl:variable>
<xsl:variable name="protocol" as="xs:string">
<xsl:value-of select="substring-before($website_uri, '://')"/>
</xsl:variable>
And I show how you use a variable: with a $ sign before the name of the value. However, to do so inside a different attribute, you need to put it between curly brackets;
...
Now I think you can do the query you're trying to achieve inline too, but I don't see a good example for it.

How to add an ID attribut to xml elements using xslt transformation

I am very new to xml and xslt transformation. I need some advice.
Basically I have managed to display a range of images from my XML page using XLTR Transformation.
The original xml has no ID's associated with each image, I cant alter the xml. Therefore I was wondering if there was a way in xslt to add an ID attribute to each image before it is outputted to the browser? As I want to be able to control each element/image individually using CSS.
I hope that makes sense?
The xslt is as follows.
<xsl:for-each select=" cars/car_type">
<!-- <h5> <xsl:value-of select="car-type"/> </h5> -->
<div class ="images">
<img>
<xsl:attribute name="src">
<xsl:value-of select="image"/>
</xsl:attribute>
</img>
</div>
</xsl:for-each>
Thanks again.
You can use generate-id (http://www.w3.org/TR/xslt#function-generate-id) function to generate an id for an input node e.g.
<xsl:for-each select="cars/car_type">
<div class="images">
<img src="{image}" id="{generate-id(image)}"/>
</div>
</xsl:for-each>
When you create the CSS elsewhere in your stylesheet you simply need to make sure you process the image elements again and use generate-id again.

Show escaped html tags from XML as well as non-escaped tags in XSLT

I have these escaped tags in my XML file: <strong> --> The whole xml is like this:
<test>
<TEST2>
<li><strong>blablablabla</li>
</TEST2>
<test>
I want to show the text in strong and bold letters (like this) and I want to show the list-item bullet. Now I only manage to show the text in strong and bold letters OR I can show the list-item bullet, but I never managed to show them both correctly. So my question is: how can I show them both in the right manner?
First, I tried <xsl:value-of select="/test/TEST2" disable-output-escaping="yes" />, which showed me the text in italic and bold version, but then, it did not output the list item bullets, because it just outputted the raw <li> tag...
Then, I tried <xsl:copy-of-select="/test/TEST">, which showed the list bullets, but this time, it also outputted the raw <strong> and <em> tags.
Besides, copy-of select, combined with disable-output-escaping did not work.
What should I do to show them both correctly?
Sample outputs:
*<em><strong>blalblblbal</strong></em> if I use the second one.
If I use the first one:
blalblblbal
Well use
<xsl:template match="li">
<xsl:copy>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:copy>
</xsl:template>
of course with other templates for ancestors of li generating a ol or ul as needed and processing child elements e.g.
<xsl:template match="test">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
But disable-output-escaping is not supported for instance for client-side XSLT in Mozilla browsers. And generally XSLT processors do not need to support it.

XSLT - output to html a specific XML element which contains formatted text - output should be same

I have an xml element which contains formatted text data :
<MESSAGE>
<TranslationReport>
Translation Report
==================
Contains errors ? true
Contains warnings ? false
There are 9 entries in the report
I want the results of my xslt (output to html) to match the contents of TranslationReport EXACTLY.
Everything I do just takes a data (all in one line - see below). This seems easy, but I have searched in all of my books and everywhere else...
Translation Report ================== Contains errors ? true Contains
warnings ? false There are 9 entries in the report
Have you tried an <xsl:output method="text"/> tag and/or enclosing the literal text in <xsl:text>...</xsl:text> tags?
If you are rendering the results in HTML, the problem is that HTML does not render newlines without enclosing the output in a tag like <pre>. Output a <pre> tag wrapping your text output in your XSLT.
The problem you are running into may have to do with the fact that in XML, different forms of white space (linebreaks, spaces, etc.) are considered equivalent. See this answer: Is it "bad practice" to be sensitive to linebreaks in XML documents?
If you are going to render to html you have two options:
use pre tag to render your text in the browser exactly as is.
parse your text with some advanced XPath 2.0 function and handle each text line as required.
Here the first option silly example:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="MESSAGE/TranslationReport">
<html>
<body>
<pre>
<xsl:value-of select="."/>
</pre>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
In the second option we will parse your text with the XPath 2.0 function tokenize, splitting all lines and wrapping each one with the eanted tag.
This is the silly example:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="MESSAGE/TranslationReport">
<html>
<body>
<xsl:for-each select="tokenize(.,'\n')
[not(position()=(1,last()))]">
<p class="TranslationReport">
<xsl:value-of select=".[position()]"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
In the second case the output will be:
<html>
<body>
<p class="TranslationReport">Translation Report</p>
<p class="TranslationReport">==================</p>
<p class="TranslationReport">Contains errors ? true</p>
<p class="TranslationReport">Contains warnings ? false</p>
<p class="TranslationReport">There are 9 entries in the report</p>
</body>
</html>