My xml:
<workorder>
<specifications>
<hpath>94 \ 72</hpath>
<classdesc></classdesc>
</specifications>
</workorder>
my xslt:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="workorder">
<xsl:apply-templates select="specifications" />
</xsl:template>
<xsl:template match="specifications">
<xsl:text>{
"Hierarchy Path"="</xsl:text>
<xsl:value-of select="translate(//workorder/specifications/hpath,'\','\\')" />
<xsl:text>"
}</xsl:text>
</xsl:template>
</xsl:stylesheet>
Expecting output is:
{
"Hierarchy Path"="94 \\ 72"
}
Current output is :
{
"Hierarchy Path"="94 \ 72"
}
Problem is: When I send json format as "Current output", not a valid json format.
If I send as "Expected output", it is a valid json format.
Please help. Thanks in advance.
With XSLT 1.0 you need a recursive approach.
You may try something like this named template.
<xsl:template name="jsonescape">
<xsl:param name="str" select="."/>
<xsl:choose>
<xsl:when test="contains($str, '\')">
<xsl:value-of select="concat(substring-before($str, '\'), '\\' )"/>
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="substring-after($str, '\')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
And call it with your strings(for example).
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="//workorder/specifications/hpath"/>
</xsl:call-template>
Related
I want to convert a XML to JSON using XSLT. But I am facing few issues.
Input XML
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<OrganizationId>123</OrganizationId>
<ActionId>123</ActionId>
<SessionId xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<EnterpriseUrl>qwe</EnterpriseUrl>
<PartnerUrl>qwe</PartnerUrl>
<Notification>
<Id>123</Id>
<sObject xsi:type="sf:Opportunity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
<sf:Id>ao123</sf:Id>
<sf:Amount>60000.0</sf:Amount>
<sf:CreatedDate>2014-11-26T14:45:52.000Z</sf:CreatedDate>
<sf:IsClosed>false</sf:IsClosed>
</sObject>
</Notification>
</notifications>
Expected Output JSON
{
"notifications": {
"OrganizationId": "123",
"ActionId": "123",
"SessionId": {
"#nil": "true"
},
"EnterpriseUrl": "qwe",
"PartnerUrl": "qwe",
"Notification": [
{
"Id": "ao123",
"sObject": {
"#type": "sf:Opportunity",
"Id": "ao123",
"Amount": "60000.0",
"CreatedDate": "2014-11-26T14:45:52.000Z",
"IsClosed": "false"
}
}
]
}
}
From this answer I got XSLT and I have tried it. This is the XSLT code I have tried. Fiddle link
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="json-xml">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="*[*]">
<xsl:param name="key" as="xs:boolean" select="false()"/>
<map>
<xsl:if test="$key">
<xsl:attribute name="key" select="local-name()"/>
</xsl:if>
<xsl:for-each-group select="*" group-by="node-name()">
<xsl:choose>
<xsl:when test="current-group()[2]">
<array key="{local-name()}">
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="false()"/>
</xsl:apply-templates>
</array>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="true()"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</map>
</xsl:template>
</xsl:stylesheet>
So below are few issues which I am facing
notifications node is missing in json output, it is the root node in the xml.
Notification should be a json array even if I receive one
item in XML
Please note that I don't want to hard code node names other than notifications and Notification in XSLT code as I may receive different nodes under node Notification.
I am looking for XSLT which can handle my requirements
Some of the requirements (outer map/JSON object, always making Notification an array) can of course be inserted into the XSLT code by modifying what you linked to (please make sure next time you show the XSLT in the question as well):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="json-xml">
<map>
<xsl:apply-templates/>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="*[*]">
<xsl:param name="key" as="xs:boolean" select="true()"/>
<map>
<xsl:if test="$key">
<xsl:attribute name="key" select="local-name()"/>
</xsl:if>
<xsl:for-each-group select="*" group-by="node-name()">
<xsl:choose>
<xsl:when test="current-group()[2] or current-grouping-key() = QName('http://soap.sforce.com/2005/09/outbound', 'Notification')">
<array key="{local-name()}">
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="false()"/>
</xsl:apply-templates>
</array>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="true()"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</map>
</xsl:template>
</xsl:stylesheet>
The code you grabbed from another question/answer I think was not written with XML having elements with attributes in mind; I have tried to adapt it below with
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="json-xml">
<map>
<xsl:apply-templates/>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="#*">
<string key="#{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="*[* or #*]">
<xsl:param name="key" as="xs:boolean" select="true()"/>
<map>
<xsl:if test="$key">
<xsl:attribute name="key" select="local-name()"/>
</xsl:if>
<xsl:apply-templates select="#*"/>
<xsl:for-each-group select="*" group-by="node-name()">
<xsl:choose>
<xsl:when test="current-group()[2] or current-grouping-key() = QName('http://soap.sforce.com/2005/09/outbound', 'Notification')">
<array key="{local-name()}">
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="false()"/>
</xsl:apply-templates>
</array>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()">
<xsl:with-param name="key" select="true()"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</map>
</xsl:template>
</xsl:stylesheet>
That seems to give the wanted attributes as #name properties of a JSON object/map for your sample; I can't guarantee it will work in general.
I got a xml that I need to turn into a json.
I'm mostly fine except with a base64 multiline
<file>TU0...AAA
FOO...BCD
FOO...012
FOO...ZYX</file>
In json multiline is not possible, this should be rewritten in 1 line only as
"file":"TU0...AAA\nFOO...BCD\nFOO...012\nFOO...ZYX"
With "real" two-char string "\n" to concatenate each line.
Can I do that in xslt 1.0 ?
I know I can use translate but that's for one char only.
I'll try
translate(.,'
',' ')
This will replace returns by space and maybe this won't break the base64 decoding of the json.
But, if i want to do it the "right way", I guess I'll need custom funcs.
In my case returns seems to be "
".
But if someone comes with a solution that works with all combinations (
) that would be great.
My primary target is chrome web browser but running fine in all browsers would be great.
If you just want to get rid of the linefeeds you could use the normalize-space($string)function, e.g.:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
exclude-result-prefixes="xd"
version="1.0">
<xd:doc scope="stylesheet">
<xd:desc>
<xd:p><xd:b>Created on:</xd:b> Apr 22, 2020</xd:p>
<xd:p><xd:b>Author:</xd:b> bwb</xd:p>
<xd:p>generates a normalized text output of the file element</xd:p>
</xd:desc>
</xd:doc>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="file"/>
</xsl:template>
<xsl:template match="file">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>
You could then still replace the whitespaces by something else( forJSON maybe with ,)
If you definitely want the \nthough, you could try the following stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
exclude-result-prefixes="xs math xd"
version="1.0">
<xd:doc scope="stylesheet">
<xd:desc>
<xd:p><xd:b>Created on:</xd:b> Apr 22, 2020</xd:p>
<xd:p><xd:b>Author:</xd:b> bwb</xd:p>
<xd:p>Override default text() template by adding a search and replace funtionality</xd:p>
</xd:desc>
</xd:doc>
<xsl:output method="text"/>
<xd:doc scope="component">
<xd:desc>The string that should be searched and replaced by $param-replaceString</xd:desc>
</xd:doc>
<xsl:param name="param-searchString" select="'
'"/><!-- actually you also wnat to replace the whitespaces, that's why the searchString looks so strange -->
<xd:doc>
<xd:desc>The string that replace any occurence of $param-searchString</xd:desc>
</xd:doc>
<xsl:param name="param-replaceString" select="'\n'"/>
<xd:doc scope="component">
<xd:desc>Override for default text() template testing for $param-searchString presence and calling replace template</xd:desc>
</xd:doc>
<xsl:template match="text()">
<xsl:choose>
<xsl:when test="contains(., $param-searchString)">
<xsl:call-template name="replace">
<xsl:with-param name="InputString" select="."/>
<xsl:with-param name="searchString" select="$param-searchString"/>
<xsl:with-param name="replaceString" select="$param-replaceString"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="InputString"/>
<xsl:param name="searchString"/>
<xsl:param name="replaceString"/>
<xsl:choose>
<xsl:when test="contains($InputString, $searchString)">
<xsl:variable name="token-before-first-match" select="substring-before($InputString, $searchString)"/>
<xsl:variable name="token-after-first-match" select="substring-after(., concat($token-before-first-match, $searchString))"/>
<xsl:value-of select="concat($token-before-first-match, $replaceString)"/>
<xsl:choose>
<xsl:when test="contains($token-after-first-match, $searchString)">
<xsl:call-template name="replace">
<xsl:with-param name="InputString" select="$token-after-first-match"/>
<xsl:with-param name="searchString" select="$searchString"/>
<xsl:with-param name="replaceString" select="$replaceString"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$token-after-first-match"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$InputString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
it's been days trying to perform a transformation to get a JSON file from XML documents. My xml doc have different levels of sub nodes, all examples I found on internet don't catch my case.
Here is my xml example:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo id="1" group="B" />
<foo id="2" group="A" />
<foo id="3", group="A">
<foo id="4" group="A" />
<foo id="5" group="A">
<foo id="6" group="A" />
<foo id="7" group="A" />
<foo id="8" group="A" />
</foo>
</foo>
<foo id="9" group="A"></foo>
</root>
desired JSON:
{
"B": {
"id": 1
},
"A": {
"id": 2
},
"A": [{
"id": 4
},
{
"A": [{
"id": 6
},
{
"id": 7
},
{
"id": 8
}
]
}
],
"A": {
"id": 9
}
}
Means whenever I have nested <foo> elements, child elements are grouped with the parent element, and so on.
I tried some xsl code (see1 and see2) and failed to make them work for my case.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="//foo"/>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="//foo">
<xsl:choose>
<xsl:when test=" count(ancestor::foo) = 1 and child::foo"/>
<xsl:when test="foo[child::foo]"/>
<xsl:otherwise>
<xsl:text>"</xsl:text><xsl:value-of select="#group"/><xsl:text>"</xsl:text>:<xsl:text> {
</xsl:text>
<xsl:text> "</xsl:text><xsl:value-of select="#id/name()"/><xsl:text>"</xsl:text>:<xsl:value-of select=" concat(' ',#id)"/>
<xsl:text>
},</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Please Check this code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="root">
<xsl:text>{</xsl:text>
<xsl:text>
</xsl:text>
<xsl:for-each select="foo">
<xsl:if test="not(child::foo)">
<xsl:text> "</xsl:text><xsl:value-of select="#group"/><xsl:text>": </xsl:text><xsl:text>{</xsl:text><xsl:text>
</xsl:text>
<xsl:text> "id": </xsl:text><xsl:value-of select="#id"/><xsl:text>
</xsl:text>
<xsl:text> }</xsl:text>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:for-each select="foo">
<xsl:if test="not(child::foo)">
<xsl:text> "</xsl:text><xsl:value-of select="#group"/><xsl:text>": </xsl:text><xsl:if test="parent::foo"><xsl:text>[</xsl:text></xsl:if><xsl:text>{</xsl:text><xsl:text>
</xsl:text>
<xsl:text> "id": </xsl:text><xsl:value-of select="#id"/><xsl:text>
</xsl:text>
<xsl:text> },</xsl:text><xsl:text>
</xsl:text>
<xsl:text> {</xsl:text><xsl:text>
</xsl:text>
<xsl:text> "</xsl:text><xsl:value-of select="#group"/><xsl:text>": </xsl:text><xsl:text>[</xsl:text><xsl:text>
</xsl:text>
</xsl:if>
<!-- <xsl:text> "</xsl:text><xsl:value-of select="#group"/><xsl:text>": </xsl:text><xsl:text>[{</xsl:text><xsl:text>
</xsl:text>-->
<xsl:for-each select="foo">
<xsl:text> {</xsl:text><xsl:text>
</xsl:text>
<xsl:text> "id": </xsl:text><xsl:value-of select="#id"/><xsl:text>
</xsl:text>
<xsl:text> }</xsl:text>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if><xsl:text>
</xsl:text>
<xsl:if test="position()=last()">
<xsl:text> ]</xsl:text><xsl:text>
</xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> }</xsl:text><xsl:text>
</xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text>],</xsl:text><xsl:text>
</xsl:text>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
<xsl:text>}</xsl:text>
</xsl:template>
</xsl:stylesheet>
It is not quite clear which result you want as the desired "JSON" has duplicated properties if there are various foo group="A" elements but in general of XML to JSON generation you can use XSLT 3 with support for XPath 3.1 maps and arrays (https://www.w3.org/TR/xpath-31/#id-maps-and-arrays) and the json output method or the xml-to-json function (https://www.w3.org/TR/xslt-30/#json, https://www.w3.org/TR/xslt-30/#func-xml-to-json), that way you have two ways of creating JSON and outputting it, you can either transform your XML directly to XPath 3.1 maps/arrays and serialize them with <xsl:output method="json"/> or you can use the usual XSLT processing to transform your input XML to the JSON XML representation the xml-to-json function expects and apply it to get the JSON as text.
Here is an example of the first approach:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-skip"/>
<xsl:strip-space elements="*"/>
<xsl:output method="json" indent="yes"/>
<xsl:template match="*[*]">
<xsl:map>
<xsl:for-each-group select="foo" group-by="#group">
<xsl:map-entry key="string(current-grouping-key())">
<xsl:choose>
<xsl:when test="not(tail(current-group()))">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="group-transform" as="map(*)*">
<xsl:apply-templates select="current-group()"/>
</xsl:variable>
<xsl:sequence select="array { $group-transform }"/>
</xsl:otherwise>
</xsl:choose>
</xsl:map-entry>
</xsl:for-each-group>
</xsl:map>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:sequence select="map { 'id' : data(#id) }"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6r5Gh3i
And here one of the second:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:mode on-no-match="shallow-skip"/>
<xsl:strip-space elements="*"/>
<xsl:output method="text"/>
<xsl:variable name="json-xml">
<xsl:apply-templates/>
</xsl:variable>
<xsl:template match="/">
<xsl:sequence select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="*[*]">
<map>
<xsl:for-each-group select="foo" group-by="string(#group)">
<xsl:choose>
<xsl:when test="not(tail(current-group()))">
<map key="{current-grouping-key()}">
<string key="id">{#id}</string>
</map>
</xsl:when>
<xsl:otherwise>
<array key="{current-grouping-key()}">
<xsl:apply-templates select="current-group()"/>
</array>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</map>
</xsl:template>
<xsl:template match="*[not(*)]">
<map>
<string key="id">{#id}</string>
</map>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6r5Gh3i/5
XSLT 3 is available using Saxon 9.8 or 9.9 HE for the Java platform on Sourceforge and Maven https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE/9.9.1-2 and for the .NET platform on NuGet https://www.nuget.org/packages/Saxon-HE/.
I have a XSL associate with an XML file. This XSL aim to create Mysql queries but in my XML I had some special characters like apostroph ' which break my queries. Do you know how I can sanitize my XSL template in order to have safe queries?
Example of my XML file
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="fnac.xsl"?>
<products xmlns="http://zanox.com/productdata/exportservice/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://zanox.com/productdata/exportservice/v1 http://productdata.zanox.com/exportservice/schema/export-1.1.xsd">
<product>
<name>jack o'connor</name>
<program>3467</program>
</product>
</products>
And my XSL file :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v1="http://zanox.com/productdata/exportservice/v1">
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//v1:product"/>
</xsl:template>
<xsl:template match="v1:product">
<xsl:text>insert into fnac (name, program) values(</xsl:text>
<xsl:value-of select="./v1:name"/>
<xsl:text>,'</xsl:text>
<xsl:value-of select="./v1:program"/>
<xsl:text>'); </xsl:text>
</xsl:template>
</xsl:stylesheet>
Thanks for your inputs!
If you want to remove apostrope from your XML file, you should use this xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v1="http://zanox.com/productdata/exportservice/v1">
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//v1:product"/>
</xsl:template>
<xsl:template match="v1:product">
<xsl:text>insert into fnac (name, program) values(</xsl:text>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="./v1:name"/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to" select="' '"/>
</xsl:call-template>
<xsl:text>,'</xsl:text>
<xsl:value-of select="./v1:program"/>
<xsl:text>'); </xsl:text>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="from"/>
<xsl:param name="to"/>
<xsl:choose>
<xsl:when test="contains($text, $from)">
<xsl:variable name="before" select="substring-before($text, $from)"/>
<xsl:variable name="after" select="substring-after($text, $from)"/>
<xsl:copy-of select="$before"/>
<xsl:value-of select="$to" disable-output-escaping="yes"/>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$after"/>
<xsl:with-param name="from" select="$from"/>
<xsl:with-param name="to" select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
which would generate output:
insert into fnac (name, program) values(jack o connor,'3467');
If you only like/need to replace the apostrope , this could be done lot easier with translate().
Try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v1="http://zanox.com/productdata/exportservice/v1">
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//v1:product"/>
</xsl:template>
<xsl:template match="v1:product">
<xsl:text>insert into fnac (name, program) values(</xsl:text>
<xsl:value-of select='translate(./v1:name,"'", " ")'/>
<xsl:text>,'</xsl:text>
<xsl:value-of select="./v1:program"/>
<xsl:text>'); </xsl:text>
</xsl:template>
</xsl:stylesheet>
We are using XSLT to translate a RIXML file to XML. Our RIXML contains the following text:
<Title><![CDATA[Looking into the future: Reiterate ‘Buy’]]></Title>
8216 is a left quote and 8217 is a right quote.
How would I replace these HTML codes with their plain text representation, or more simply, just a single quote? This is XSLT version 1.0.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vQ2">""</xsl:variable>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select=
"translate(.,'‘’',$vQ2)"/>
</xsl:template>
</xsl:stylesheet>
I came upon this function which worked well for me. I call it to replace all the characters I need to:
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text"
select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>