Problem
I'm making a UWP (Universal Windows Platform) app. I'm trying to convert .xml and .xsl into .html file to make a pdf file finally, but XslCompiledTransform throws an error when loading .xsl file on Visual Studio 2022. I have no idea about on which platform XSLT compilation isn't supported neither which platform I'm now on. I couldn't find relevent information on Google. Any help is greatly appreciated.
Source code
MainPage.xaml.cs
private async void ConvertXML2HTML(IStorageFile xmlFile, IStorageFile xslFile)
{
Windows.Storage.Streams.IRandomAccessStream xslStream = await xslFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
System.IO.Stream xslStreamNet = xslStream.AsStream();
XmlReader xmlReaderXsl = System.Xml.XmlReader.Create(xslStreamNet);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xmlReaderXsl, settings, null); // This line throws
// System.PlatformNotSupportedException: 'Compilation of XSLT is not supported on this platform.'
}
Package.appxmanifest
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
...
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
...
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
</Package>
xsl file used in the code above.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<META http-equiv="X-UA-Compatible" content="IE=11" />
<title>document title</title>
<style type="text/css">
...
</style>
</head>
<body style="word-break:break-all;">
<table border="0" width="100%" style="center" >
<td align="center" style="vertical-align:top;">
<xsl:apply-templates/>
</td>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="SomeString">
<xsl:if test="count(Text)!=0">
<xsl:call-template name="loop">
<xsl:with-param name="end_1" select="count(Text)" />
<xsl:with-param name="count_1" select="1" />
</xsl:call-template>
</xsl:if>
...
<xsl:template name="zero-padding">
<xsl:param name="str"/>
<xsl:choose>
<xsl:when test="$str!=''"><xsl:value-of select="number($str)"/></xsl:when>
<xsl:when test="$str=''">0</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="zero-padding2">
<xsl:param name="str"/>
<xsl:choose>
<xsl:when test="$str!=''"><xsl:value-of select="number($str)"/>.</xsl:when>
<xsl:when test="$str=''">0.</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="*">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
</xsl:stylesheet>
What I tried
Though I knew it is not a JScript error, I tried the code below. It didn't work.
XslCompiledTransform xslt = new XslCompiledTransform();
var settings = new XsltSettings();
settings.EnableScript = true;
xslt.Load(xmlReaderXsl, settings, null);
Related
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 .
i am replacing 
 with br tag to show new line while transforming xml using xsl. i want to replace blank spaces to its according code that may   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>
I have an ecommerce cart which generates the XML at runtime. I have access to the XSL stylesheet which styles the actual XML.
I would like to display product category images in the menu. Is there an example of running a query within an xsl file that you could show me?
I cant see where its pulling the category data from?
can you help?
<?xml version="1.0" standalone="yes" ?>
<!-- ###################################################################################################### -->
<!-- Copyright AspDotNetStorefront.com, 1995-2009. All Rights Reserved. -->
<!-- http://www.aspdotnetstorefront.com -->
<!-- For details on this license please visit the product homepage at the URL above. -->
<!-- THE ABOVE NOTICE MUST REMAIN INTACT. -->
<!-- ###################################################################################################### -->
<package version="2.1" displayname="Categories" debug="false" includeentityhelper="true">
<PackageTransform>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:aspdnsf="urn:aspdnsf" exclude-result-prefixes="aspdnsf">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:param name="CategoryID">
<xsl:choose>
<xsl:when test="/root/System/PageName = 'showmanufacturer.aspx' or /root/System/PageName = 'showsection.aspx' or /root/System/PageName = 'showdistributor.aspx' or /root/System/PageName = 'showvector.aspx' or /root/System/PageName = 'showgenre.aspx'">0</xsl:when>
<xsl:when test="/root/System/PageName = 'showcategory.aspx' and boolean(/root/QueryString/categoryid)">
<xsl:value-of select="/root/QueryString/categoryid"/>
</xsl:when>
<xsl:when test="(/root/System/PageName = 'showcategory.aspx' or /root/System/PageName = 'showproduct.aspx') and boolean(/root/Cookies/LastViewedEntityInstanceID) and /root/Cookies/LastViewedEntityName = 'Category'">
<xsl:value-of select="/root/Cookies/LastViewedEntityInstanceID"/>
</xsl:when>
<xsl:otherwise>
0
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:param name="AncestorID">
<xsl:for-each select="/root/EntityHelpers/Category//Entity[EntityID = $CategoryID]">
<xsl:value-of select="ancestor::*/EntityID"/>
</xsl:for-each>
</xsl:param>
<xsl:param name="ParentID">
<xsl:for-each select="/root/EntityHelpers/Category//Entity[EntityID = $CategoryID]">
<xsl:value-of select="parent::*/EntityID"/>
</xsl:for-each>
</xsl:param>
<xsl:template match="/">
<xsl:element name="ul">
<xsl:attribute name="class">
<![CDATA[menuul]]>
</xsl:attribute>
<xsl:apply-templates select="/root/EntityHelpers/Category/Entity">
<xsl:with-param name="prefix" select="''"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="Entity">
<xsl:param name="prefix"></xsl:param>
<xsl:param name="eName" select="aspdnsf:GetMLValue(Name)" />
<xsl:choose>
<xsl:when test="Published=1">
<li class="menuli">
<xsl:value-of select="$prefix" />
<!--<xsl:if test="number(ParentEntityID) != 0">
<span class="catMark">>></span>�
</xsl:if>-->
<a href="{concat('c-',EntityID,'-',SEName,'.aspx')}">
<xsl:if test="EntityID = $CategoryID or descendant::Entity/EntityID = $CategoryID">
<xsl:attribute name="class">MenuSelected</xsl:attribute>
</xsl:if>
<xsl:value-of select="$eName" disable-output-escaping="yes"/>
</a>
<xsl:if test="count(child::Entity)>0">
<ul class="submenuul">
<xsl:apply-templates select="Entity">
<xsl:with-param name="prefix" select="concat($prefix, '��')"/>
</xsl:apply-templates>
</ul>
</xsl:if>
</li>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
</PackageTransform>
</package>
If you are using ASP.NET you can use standard ASP.NET XML Control.
On page load assign to it your xml and xsl files like below:
protected void Page_Load(object sender, EventArgs e)
{
Xml1.DocumentSource = "~/App_Data/YourXmlFile.xml";
Xml1.TransformSource = "~/App_Data/YourXslStyleSheetFile.xsl";
}
You can also use DocumentContent property your xml is stored not in files but, i.e. in database.
See example here
The accepted answer is true to ASP.Net, but not to Aspdotnetstorefront. The XML file referenced in the question is only generated if debug is enabled and it should not be generated on any production environments (you will end up with write conflicts).
The XML behind the XSLT is generated for you at runtime. The category data (and other entity data) is included because you have includeentityhelper="true". EntityHelper caches category (and other entity) data to reduce DB queries. If you need data in addition to this, you should use the XMLPackage <query> node documented here (under 'SQL Queries'):
http://manual.aspdotnetstorefront.com/p-157-xml-packages.aspx
You'll also find the '' node used in most of the XMLPackages included in the default build.
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.
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>