xsl replace specific character in string - html

I am studying XSL and I have question about replacing specific character in string.
we have xml file
<family>
-<familyid id="first">
--<name>smith</name>
--<image>fatherpic\myfather.jpg</image>
and i would like get image path to insert picture.
For example, we have path "fatherpic\myfather.jpg"
then i would like select "fatherpic/myfather.jpg"
which mean i would like to change"/" to"\".
i was trying to use translate function. but it didn't work.
does any can give example ? thanks

The following xslt will print replace the '\' with '/' in the image element and will print the rest of the xml file unchanged.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<xsl:template match="image">
<image>
<xsl:value-of select="translate(., '\', '/')" />
</image>
</xsl:template>
</xsl:stylesheet>

As you said in your post, you could use the translate function.
The following stylesheet extracts the value of the image value and outputs it like text after doing the described string translation. This is just an example of how to use the translate function.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no" />
<xsl:template match="text()" />
<xsl:template match="image">
<xsl:value-of select="translate(., '\', '/')" />
</xsl:template>
</xsl:stylesheet>
Hope it helps.

Related

XSLT translate backslash to double backslash

I need to transform this value:
<MediaFile>F:\DEMO\TEST\HELLO.pm4</MediaFile>
to this:
<MediaFile>F:\\DEMO\\TEST\\HELLO.pm4</MediaFile>
I have tried a lot of thing, translate, concat, substring and replace but I didn't succeeded.
Here's precisely, what I've tried:
Source file:
<?xml version="1.0" encoding="UTF-8" ?>
<Asset version="1.0">
<Target>
<Name>HELLO</Name>
<MediaFile>F:\DEMO\TEST\HELLO.mp4</MediaFile>
</Target>
</Asset>
XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text" indent="yes" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:variable name="MediaFile">
<xsl:value-of select="Asset/Target/MediaFile"/>
</xsl:variable>
<xsl:variable name="Media">
<xsl:value-of select="replace($MediaFile,'\','\\')"/>
</xsl:variable>
<xsl:element name="Media">
<xsl:value-of select="$Media"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I'm using xslt 2.0
Any idea? Thanks
You would need to replace the below
<xsl:value-of select="replace($MediaFile,'\','\\')"/>
with
<xsl:value-of select="replace($MediaFile,'\\','\\\\')" />
In many programming languages, backslash is used to as an escape character to indicate the character following it needs special treatment. In this case, you would need to escape the character being replaced \ with \\ and also need to replace \\ with \\\\ (two backslashes).
Following question would help provide some detail explanation What does back slash "\" really mean?
Additionally, in the template that you have shared, the desired output is text, so there is no need to create an element named Media as it would come into picture if the desired output is XML. So the template code can be optimized as
<xsl:template match="/">
<xsl:value-of select="replace(Asset/Target/MediaFile,'\\','\\\\')" />
</xsl:template>
Output
F:\\DEMO\\TEST\\HELLO.mp4

Normalize space issue with html tags

Here's one for you XSLT gurus :-)
I have to deal with XML output from a Java program I cannot control.
In the docs outputted by this app the html tags remain as
<u><i><b><em>
etc, instead of
<u><i><b><em> and so on.
That's not a massive problem, I use XSLT to fix that, but using normalize-space to remove excess whitespace also removes spaces before these html tags.
Example
<Locator Precode="7">
<Text LanguageId="7">The next word is <b>bold</b> and is correctly spaced
around the html tag,
but the sentence has extra whitespace and
line breaks</Text>
</Locator>
If I run the XSLT script we use to remove extra white space, of which this is the relevant part
<xsl:template match="text(.)">
<xsl:value-of select="normalize-space()"/>
</xsl:template>
In the resulting output the xslt has correctly removed the extra whitespace and the line breaks, but it has also removed the space before the tag resulting in this output :-
The next word isboldand is correctly spaced around the html tag, but the sentence has extra whitespace and line breaks.
The spacing before and after the word "bold" has been stripped as well.
Anyone have any ideas how to prevent this from happening? Pretty well at my wits end so any help will be greatly appreciated!
:-)
Hi again,
Yes of course, here's the full stylesheet. We have to deal with the html tags and spacing in one pass
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8"/>
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Text//*">
<xsl:value-of select="concat('<',name(),'>')" />
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
<xsl:template match="Instruction//*">
<xsl:value-of select="concat('<',name(),'>')" />
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
<xsl:template match="Title//*">
<xsl:value-of select="concat('<',name(),'>')" />
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
</xsl:stylesheet>
An XSLT 1.0 solution is an XPath expression to replace a sequence of several whitespace characters with a single one. The idea is not my own, it is taken from an answer by Dimitre Novatchev.
The advantage over the built-in normalize-space() function is that trailing whitespace (in your case, before and after the b element) is kept.
EDIT: As a response to you editing your question. Below is the said XPath expression incorporated into your stylesheet. Also:
Explicitly saying omit-xml-declaration="no" is redundant. It is the default action taken by the XSLT processor
Several of your templates have the same content. I summarized them using | to a single one.
Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Text//*|Instruction//*|Title//*">
<xsl:value-of select="concat('<',name(),'>')" />
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select=
"concat(substring(' ', 1 + not(substring(.,1,1)=' ')),
normalize-space(),
substring(' ', 1 + not(substring(., string-length(.)) = ' '))
)
"/>
</xsl:template>
</xsl:stylesheet>
XML Output
<?xml version="1.0" encoding="UTF-8"?>
<Locator Precode="7">
<Text LanguageId="7">The next word is <b>bold</b> and is correctly spaced around the html tag, but the sentence has extra whitespace and line breaks</Text>
</Locator>

How have xsl:function return a string value including html tags

I am attempting to transpose a java function to an xsl:function spec.
The function basically places html tags around substrings.
I now bump into difficulties: using the java inline code this works perfectly, but I am unable to figure out how to prevent output escaping when using the xsl:function.
How can I achieve the output to contain the wanted html tags?
A simplified example of what I am trying to achieve is the following:
input parameter value "AB" should lead to a string A<b>B</b>, shown in html browser as AB of course.
Example function I tried is the below; but then the resulting string is A&lt ;b&gt ;B&lt ;/b&gt ; (note that I had to add blanks to prevent the entities from getting interpreted in this editor), which of course shows up in browers as A<b>B</b>.
Note that xsl:element cannot be used in the xsl:function code, because that has no effect; I want the string result of the function call to contain < and > characters, and then add the string result to the output result file.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:custom="http://localhost:8080/customFunctions">
<xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
<xsl:function name="custom:test">
<xsl:param name="str"/>
<xsl:value-of select="substring($str,1,1)"/>
<xsl:text disable-output-escaping="yes"><![CDATA[<b>]]></xsl:text>
<xsl:value-of select="substring($str,2)"/>
<xsl:text disable-output-escaping="yes"><![CDATA[</b>]]></xsl:text>
</xsl:function>
<xsl:template match="/">
<xsl:element name="html">
<xsl:element name="body">
<xsl:value-of select="custom:test('AB')"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Here is an example, use sequence instead value-of and make sure your function returns nodes (which is usually simply done by writing literal result elements):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:custom="http://localhost:8080/customFunctions"
exclude-result-prefixes="custom">
<xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
<xsl:function name="custom:test">
<xsl:param name="str"/>
<xsl:value-of select="substring($str,1,1)"/>
<b>
<xsl:value-of select="substring($str,2)"/>
</b>
</xsl:function>
<xsl:template match="/">
<xsl:element name="html">
<xsl:element name="body">
<xsl:sequence select="custom:test('AB')"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

how to interpret HTML in XSL

I have the following xml
<results>
<first-name>Carl<first-name>
<data><b> This is carl's data </b></data>
</results>
How do I include the bold tags which is present in the <data> tag to be a part of the output but rendered as an HTML
When I say <xsl:value-of select="results/data"/> The output is
<b> This is carl's data </b>
I want to achieve "This is carl's data" as the output in bold.
Well <xsl:copy-of select="results/data/node()"/> is a start but if the requirement is part of a larger problem then you are better off writing a template for data elements which uses apply-templates to push the child nodes through some template(s) for copying HTML elements through to the output.
I am sure someone will let me know if I am being naive:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/results">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="first-name">
<xsl:value-of select="." />
<xsl:text>: </xsl:text>
</xsl:template>
<xsl:template match="data">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="b">
<b>
<xsl:value-of select="." />
</b>
</xsl:template>
</xsl:stylesheet>

Using XSLT as xhtml link extractor

I'm starting using XSLT and write this scipt:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="span[#class='thumb']" >
Link: <xsl:value-of select="$base" /><xsl:value-of select="a/#href" />
</xsl:template>
<xsl:template match="/">
Base href: <xsl:value-of select="$base" />
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
And using this command:
xsltproc --html --param base "'http://example.com'" lista.xslt test.html
I need to get list of Links, but I get whole page on output. What's wrong? How can I get it works?
There are some default templates which are unseen here. The really easy way to resolve it is to just explicitly limit to the span elements you're matching as below. Otherwise, you can override the default templates.
<xsl:template match="/">
Base href: <xsl:value-of select="$base" />
<xsl:apply-templates select="//span[#class='thumb']" />
</xsl:template>
There's a default template that matches essentially everything if you let it. Your 4th last line calls that template.
That's part of the problem. The rest can probably be taking care of by matching just the stuff you're looking for, directly in the top-level template.