replacement of multiple characters in a single element of xml using XSL - c#

i am replacing &#10 with br tag to show new line while transforming xml using xsl. i want to replace blank spaces to its according code that may &nbsp or something else at the same time.sample code is below. please suggest for me what should i do.
while xml file may be as ------------
<?xml version="1.0" encoding="iso-8859-1"?><?xml-stylesheet type="text/xsl"
href="task.xsl"?><Nodes><sNode><Word><![CDATA[1
2.............3............4............5
3]]></Word></sNode></Nodes>
since blank spaces ommitted automatically so here ........ represents blank spaces.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:for-each select="Nodes/sNode">
<tr>
<td>
<xsl:call-template name="replace-string-with-element">
<xsl:with-param name="text" select="Word"/>
<xsl:with-param name="replace" select="'
'"/>
<xsl:with-param name="with" select="'br'"/>
</xsl:call-template>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="replace-string-with-element">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="with"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:element name="{$with}"/>
<xsl:call-template name="replace-string-with-element">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="with" select="$with"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

You could use xsl:character-map as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn xs">
<xsl:character-map name="replaceChars">
<xsl:output-character character="
" string="br"/>
</xsl:character-map>
<xsl:output method="xml" version="1.0" encoding="UTF-8" use-character-maps="replaceChars" indent="yes"/>
<!-- Implement your templates -->
</xsl:stylesheet>
It is even possible to save all characters in a xsl:character-map in an external XSLT and use <xsl:import href="characterFile.xslt" />
To implement this in your stylesheet use the following XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:character-map name="replaceChars">
<xsl:output-character character="
" string="br"/>
</xsl:character-map>
<xsl:output method="html" use-character-maps="replaceChars"/>
<xsl:template match="/">
<html>
<body>
<table>
<xsl:for-each select="Nodes/sNode">
<tr>
<td>
<xsl:value-of select="Word" />
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

Related

XSLT transformation and replacing placeholders

I'm not very good at XSLT, so hopefully someone can help :)
I'm trying to convert an HTML template (called from C# code), replacing placeholders with data from an XML file.
The (simplified) HTML template looks like:
<html>
<body>
Dear $firstName $lastName,
</body>
</html>
The XML file looks like:
<inputXml>
<firstName>Joske</firstName>
<lastName>Vermeulen</lastName>
</inputXml>
And the XSLT I came up with so far looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
version="1.0"
xmlns:s0="http://www.w3.org/1999/xhtml">
<xsl:output omit-xml-declaration="yes" method="text" version="1.0" />
<xsl:variable name="templateMessage" select="document('stream:///TemplateMessage')" />
<xsl:variable name="inputData" select="/" />
<xsl:template match="/">
<xsl:apply-templates select="$templateMessage/*/node()" />
</xsl:template>
<xsl:template match="*/*">
<xsl:value-of select="$inputData//*[name()=name(current())]"/>
</xsl:template>
</xsl:stylesheet>
For some reason the output of the transformation is just empty, because the last match is probably not correct. (If I omit the last match, I get the original HTML template as output).
Anyone sees what I did wrong?
Ok, found a solution.
The template has placeholders like this:
<html>
<body>
Dear <span class="placeholder">firstName</span> <span class="placeholder">lastName</span>,
</body>
</html>
And the XSLT looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
version="1.0"
xmlns:s0="http://www.w3.org/1999/xhtml">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<!-- This is the XML data to use to replace the placeholders in the HTML template with -->
<xsl:variable name="inputData" select="document('stream:///InputData')" />
<xsl:variable name="placeholders">
<list>
<placeholder id="firstName" value="{$inputData/inputXml/firstName}" />
<placeholder id="lastName" value="{$inputData/inputXml/lastName}" />
</list>
</xsl:variable>
<!-- Take the HTML template -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Replace every placeholder in the HTML template with the value from the XML data defined by its XPATH -->
<xsl:template match="span[#class='placeholder']">
<xsl:variable name="this" select="node()"/>
<xsl:value-of select="msxsl:node-set($placeholders)/list/placeholder[#id = $this]/#value" />
</xsl:template>
</xsl:stylesheet>
For just simple replacing the $firtstname and $lastname from the xml file I tried something like this and it works. Let me know if something is not clear. Just sharing with you in case it helps.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
version="2.0">
<xsl:variable name="templateMessage" select="document('MyXmldata.xml')" />
<xsl:variable name="inputData" select="/" />
<xsl:template match="/">
<html>
<body>
<xsl:variable name="firstName" select="$templateMessage/inputXml/firstName" />
<xsl:variable name="lastName" select="$templateMessage/inputXml/lastName" />
<xsl:variable name="StringValue" select="node()" />
<xsl:variable name="StringValue1" select="replace($StringValue,'\$firstName',$firstName)" />
<xsl:variable name="StringValue2" select="replace($StringValue1,'\$lastName',$lastName)" />
</body>
</html>
</xsl:template>
May be this code can help you .

How do I convert Richtext images from a standard WPF RichTextBox into HTML using XSLT?

How do I convert Richtext images from a standard WPF RichTextBox into HTML using XSLT?
Based on this answer, I have made the following XSLT file. So far, it converts Bold, Italic, Underlined, font family, font size, and font color. Now I still need it to convert images in the Richtext to HTML.
Image alignment does not have to be considered.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl x">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="x:Section[not(parent::x:Section)]">
<div>
<xsl:apply-templates select="node()"/>
</div>
</xsl:template>
<xsl:template match="x:Section">
<xsl:apply-templates select="node()"/>
</xsl:template>
<xsl:template match="x:Paragraph">
<p>
<xsl:apply-templates select="node()"/>
</p>
</xsl:template>
<xsl:template match="x:Run">
<xsl:variable name="style">
<xsl:if test="#FontStyle='Italic'">
<xsl:text>font-style:italic;</xsl:text>
</xsl:if>
<xsl:if test="#FontWeight='Bold'">
<xsl:text>font-weight:bold;</xsl:text>
</xsl:if>
<xsl:if test="contains(#TextDecorations, 'Underline')">
<xsl:text>text-decoration:underline;</xsl:text>
</xsl:if>
<xsl:if test="#FontSize != ''">
<xsl:text>font-size:</xsl:text>
<xsl:value-of select="#FontSize" />
<xsl:text>pt;</xsl:text>
</xsl:if>
<xsl:if test="#FontFamily != ''">
<xsl:text>font-family:</xsl:text>
<xsl:value-of select="#FontFamily" />
<xsl:text>;</xsl:text>
</xsl:if>
<xsl:if test="#Foreground != ''">
<xsl:text>color:#</xsl:text>
<xsl:value-of select="substring(#Foreground, 4)"/>
<xsl:text>;</xsl:text>
</xsl:if>
</xsl:variable>
<span>
<xsl:if test="normalize-space($style) != ''">
<xsl:attribute name="style">
<xsl:value-of select="normalize-space($style)"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="text()"/>
</span>
</xsl:template>
</xsl:stylesheet>
You could add this template - include it above the final </xsl:stylesheet>
<xsl:template match="x:Image">
<img src="#Source" />
</xsl:template>

I want perform sum of product of two elements at differnt levels

I tried for following code but its not working. I have taken one string and write XSLT in it and load it XslCompiledTransform object.
<xsl:sequence select=
"sum(//Item/(cost * related_id/Item/quantity))"/>
Source XML:
<AML>
<Item>
<cost>
40
</cost>
<related_id>
<Item>
<quantity>2</quantity>
</Item>
</related_id>
</Item>
<Item>
<cost>
50
</cost>
<related_id>
<Item>
<quantity>10</quantity>
</Item>
</related_id>
</Item>
</AML>
As I said in the comments, xsl:sequence and that XPath syntax you're trying to use aren't available in XSLT 1.0 (which XslCompiledTransform uses), but you can achieve a sum of formulas by using a recursive template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="SumSet">
<xsl:with-param name="items" select="/*/Item" />
</xsl:call-template>
</xsl:template>
<xsl:template name="SumSet">
<xsl:param name="items" />
<xsl:if test="$items">
<xsl:variable name="currentValue">
<xsl:apply-templates select="$items[1]" />
</xsl:variable>
<xsl:variable name="remainderSum">
<xsl:call-template name="SumSet">
<xsl:with-param name="items" select="$items[position() > 1]" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$currentValue + $remainderSum"/>
</xsl:if>
<xsl:if test="not($items)">0</xsl:if>
</xsl:template>
<xsl:template match="Item">
<xsl:value-of select="cost * related_id/Item/quantity"/>
</xsl:template>
</xsl:stylesheet>
When this is run on your input XML, the result is:
580
That would be the generic approach, but since you've mentioned that you're using XslCompiledTransform, you can use msxsl:node-set() to simplify this task a bit:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="values">
<xsl:apply-templates select="/*/Item" />
</xsl:variable>
<xsl:value-of select="sum(msxsl:node-set($values)/*)"/>
</xsl:template>
<xsl:template match="Item">
<itemValue>
<xsl:value-of select="cost * related_id/Item/quantity"/>
</itemValue>
</xsl:template>
</xsl:stylesheet>
This also produces the value 580 when run on your input XML.

XML to treeview based on ParentId

I have an XML like this:
<table name="tblcats">
<row>
<Id>1741</Id>
<Industry>Oil & Gas - Integrated</Industry>
<ParentId>1691</ParentId>
</row>
<row>
<Id>1690</Id>
<Industry>Commodities</Industry>
<ParentId>1691</ParentId>
</row>
<row>
<Id>1691</Id>
<Industry>Capital Goods</Industry>
<ParentId>0</ParentId>
</row>
</table>
I want to create a Treeview from this XML so that table is parent node and then nodes ParentId 0 is second parent and then child nodes with Parent Id greater than 0
Like this:
+Table
+Capital Goods
Commodities
Oil & Gas - Integrated
How can I do this? Please suggest
Regards,
Asif Hameed
A fairly simplistic approach would be to use the standard ASP.NET controls XmlDataSource and TreeView and use an XSLT transform file to transform the XML you have into something that the TreeView control likes.
So, assuming you have the XML above in a file called cats.xml, the ASP.NET page markup would look like:
<asp:XmlDataSource ID="CatsXml" runat="server" DataFile="~/cats.xml" TransformFile="~/cats.xslt"></asp:XmlDataSource>
<asp:TreeView ID="CatsTree" runat="server" DataSourceID="CatsXml">
<DataBindings><asp:TreeNodeBinding TextField="name" ValueField="id" /></DataBindings>
</asp:TreeView>
and the XSLT file (cats.xslt) would be:
<?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="xml" indent="yes"/>
<xsl:template match="table">
<table id="-1" name="Table">
<xsl:for-each select="/table/row[ParentId = 0]">
<industry>
<xsl:attribute name="id">
<xsl:value-of select="Id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="Industry"/>
</xsl:attribute>
<xsl:call-template name="industry-template">
<xsl:with-param name="pId" select="Id" />
</xsl:call-template>
</industry>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="industry-template">
<xsl:param name="pId" />
<xsl:for-each select="/table/row[ParentId = $pId]">
<industry>
<xsl:attribute name="id">
<xsl:value-of select="Id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="Industry"/>
</xsl:attribute>
<xsl:call-template name="industry-template">
<xsl:with-param name="pId" select="Id" />
</xsl:call-template>
</industry>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Stuart.

xslt help - my transform is not rendering correctly

I'm trying to apply an xlst transformation using the following file. This is very basic, but I wanted to build off of this when I get it working correctly.
<?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:template match="/">
<div>
<h2>Station Inventory</h2>
<hr/>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="StationInventory">
<h5><xsl:value-of select="station-name" /></h5>
<xsl:apply-templates select="detector"/>
</xsl:template>
<xsl:template match="detector">
<span>
<xsl:value-of select="detector-name" />
</span>
<br/>
</xsl:template>
</xsl:stylesheet>
Here is some xml I'm using for the source.
<StationInventoryList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.dummy-tmdd-address">
<StationInventory>
<station-id>9940</station-id>
<station-name>Zone 9940-SEB</station-name>
<station-travel-direction>SEB</station-travel-direction>
<detector-list>
<detector>
<detector-id>2910</detector-id>
<detector-name>1999 West Smith Exit SEB</detector-name>
</detector>
<detector>
<detector-id>9205</detector-id>
<detector-name>CR-155 Exit SEB</detector-name>
</detector>
<detector>
<detector-id>9710</detector-id>
<detector-name>Pt of View SEB</detector-name>
</detector>
</detector-list>
</StationInventory>
</StationInventoryList>
Any ideas what I'm doing wrong? The simple intent here is to make a list of station, then make a list of detectors at a station. This is a small piece of the XML. It would have multiple StationInventory elements.
I'm using the data as the source for an asp:xml control and the xslt file as the transformsource.
var service = new InternalService();
var result = service.StationInventory();
invXml.DocumentContent = result;
invXml.TransformSource = "StationInventory.xslt";
invXml.DataBind();
Any tips are of course appreciated. Have a terrific weekend.
Cheers,
~ck
Replace by
<?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" xmlns:st="http://www.dummy-tmdd-address">
<xsl:template match="/">
<div>
<h2>Station Inventory</h2>
<hr/>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="st:StationInventory">
<h5><xsl:value-of select="st:station-name" /></h5>
<ul>
<xsl:apply-templates select="st:detector-list/st:detector"/>
</ul>
</xsl:template>
<xsl:template match="st:detector">
<li>
<xsl:value-of select="st:detector-name" />
</li>
</xsl:template>
</xsl:stylesheet>
because detector is child of detector-list not station inventory and there is a namespace
There are two obvious problems:
All elements in the XML document are in the default namespace, but in the XSLT code they are referenced as belonging to "no namespace".
The element <StationInventory> doesn't have any <detector> children.
Solution:
In the XSLT stylesheet below the above two problems are corrected:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.dummy-tmdd-address">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<div>
<h2>Station Inventory</h2>
<hr/>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="d:StationInventory">
<h5><xsl:value-of select="d:station-name" /></h5>
<xsl:apply-templates select="d:detector-list/d:detector"/>
</xsl:template>
<xsl:template match="d:detector">
<span>
<xsl:value-of select="d:detector-name" />
</span>
<br/>
</xsl:template>
</xsl:stylesheet>
The result now is a complete output, that most probably was wanted:
<div xmlns:d="http://www.dummy-tmdd-address">
<h2>Station Inventory</h2>
<hr />
<h5>Zone 9940-SEB</h5>
<span>1999 West Smith Exit SEB</span>
<br />
<span>CR-155 Exit SEB</span>
<br />
<span>Pt of View SEB</span>
<br />
</div>

Categories

Resources