XSLT to transform HTML to Markdown not working - c#

I'm using the XSLT found here to transform content in HTML to Markdown format but the results I'm getting are plain text without the Markdown formatting syntax. Here's the function I'm using:
private static string ConvertToText()
{
string text = string.Empty;
XmlDocument xsl = new XmlDocument();
xsl.CreateEntityReference("nbsp");
xsl.Load(System.Web.HttpContext.Current.Server.MapPath("/Test/markdown.xslt"));
XmlReader xr = XmlReader.Create(System.Web.HttpContext.Current.Server.MapPath("/Test/html.xml"));
//creating stringwriter
StringWriter writer = new System.IO.StringWriter();
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xsl);
xslt.Transform(xr, null, writer);
//return string
text = writer.ToString();
writer.Close();
return text;
}
Can anyone tell me why it's not working?
Thanks.

I guess your problem is the xmlns in your input XML. Try either to remove it in the xr variable before you transform it or to adjust your XSL file with namespace declarations like:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:html="http://www.w3.org/1999/xhtml">
...
<xsl:template match="html:h3">
...

Related

Transforming XML to valid HTML with XmlDocument

I have XML and XSL I want to transform to valid HTML. Source and targets are XmlDocuments.
I have this code:
public static XmlDocument XslTransformation(XslCompiledTransform xslt, XmlDocument input)
{
XmlDocument target = new XmlDocument();
using (var writer = XmlWriter.Create(target.CreateNavigator().AppendChild(), xslt.OutputSettings))
{
xslt.Transform(input, writer);
}
return target;
}
In XSL we set output method:
<xsl:output method="html" version="1.0" encoding="iso-8859-1" indent="yes" omit-xml-declaration="no"/>
But result is not valid HTML. For example
<script src="blah.js"></script>
is converted to
<script src="blah.js" />
I checked OutputMethod of XSLT OutputSettings and it is set to "Html".
I found many related questions and accepted answers but I dont understand why I am still getting self-closing tags.

I have an xml file that is styled with xslt to produce html email template. How can i get that xml as html email body in c#?

I have an xml file that is styled with xslt to produce html email template. I get values from users dynamically and replace xml elements text with the values received. How can i get that xml file and send as html email body in c#?
My Xml Looks Like This
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="EmailTemplateStyleForHTML.xslt"?>
<EmailTemplate>
<subject>Information from xyz</subject>
<displayName>abcd</displayName>
<Message1>
Thanks you for registering to xyz.
</Message1>
<Copyright>Copyright xyz</Copyright>
</EmailTemplate>
I am using LINQ to set the values to the xml.
Note: I know how to get and set the values from xml but what i want is to grab the whole xml file in to the email body.
If you think there is a better approach for this i would love to hear that. I would really appreciate your help.
Edited after Reply:
The xsl transformation part :
TextReader tr1 = new StringReader(#"EMailTemplateHtml.xml");
var tr11 = new XmlTextReader(tr1);
var xPathDocument = new XPathDocument(tr11);
//read XSLT
TextReader tr2 = new StringReader(#"EmailTemplateStyleForHTML.xslt");
var tr22 = new XmlTextReader(tr2);
var xslt = new XslTransform();
xslt.Load(tr22);
var sb = new StringBuilder();
TextWriter tw = new StringWriter(sb);
xslt.Transform(xPathDocument, null, tw);
emailBody = sb.ToString();
I am doing the transformation as you said(#Roy Ashbrook) am i missing anything here?
I believe you will need to actually perform the XSL transform in memory, not reference it in the XML itself. It's possible you could store the XSL in a remote location and reference it that way, but I wouldn't
so:
inject your values into your xml string
transform your xml using your xsl
make that your html message body
Here is some code. Mostly borrowed from/inspired by:
How to transform XML as a string w/o using files in .NET? and Sending E-mail using C#.
void Main()
{
SendHtmlBody(GetHtmlBody());
}
void SendHtmlBody(string HtmlBody){
using(SmtpClient c = new SmtpClient())
{
//set smtp options here
using(MailMessage msg = new MailMessage("from#replace.me","to#replace.me"))
{
msg.Subject = "Testing Bulk mail application";
msg.Body = HtmlBody;
msg.IsBodyHtml = true;
//c.Send(msg);
}
}
}
string GetHtmlBody(){
string xmlInput = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<EmailTemplate>
<subject>Information from xyz</subject>
<displayName>abcd</displayName>
<Message1>
Thanks you for registering to xyz.
</Message1>
<Copyright>Copyright xyz</Copyright>
</EmailTemplate>";
string xslInput = #"<?xml version=""1.0"" encoding=""ISO-8859-1""?>
<xsl:stylesheet version=""1.0""
xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:template match=""/"">
<html>
<body>
<h5><xsl:value-of select=""EmailTemplate/subject""/></h5>
<h5><xsl:value-of select=""EmailTemplate/displayName""/></h5>
</body>
</html>
</xsl:template>
</xsl:stylesheet>";
using (StringReader srt = new StringReader(xslInput)) // xslInput is a string that contains xsl
using (StringReader sri = new StringReader(xmlInput)) // xmlInput is a string that contains xml
{
using (XmlReader xrt = XmlReader.Create(srt))
using (XmlReader xri = XmlReader.Create(sri))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xrt);
using (StringWriter sw = new StringWriter())
using (XmlWriter xwo = XmlWriter.Create(sw, xslt.OutputSettings)) // use OutputSettings of xsl, so it can be output as HTML
{
xslt.Transform(xri, xwo);
return sw.ToString();
}
}
}
}

Add <?xml version="1.0" ?> to the top of a xml file after xsl transform

I have successfully been able to transform a simple xml file with data to another xml file (excel template) using a xsl template, this is what my xsl file looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" standalone="yes"/>
<xsl:template match="/">
<xsl:processing-instruction name="mso-application">
<xsl:text>progid="Excel.Sheet"</xsl:text>
</xsl:processing-instruction>
...(stuff here)...
</xsl:template>
</xsl:stylesheet>
The resulting xml file is written out correctly BUT with the exception of including
<?xml version="1.0"?>
at the top of the file. How can I get it to appear at the top?
Currently my resulting xml file starts with:
<?mso-application progid="Excel.Sheet"?>
...(rest of file)...
But what I need it to do is:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
.(rest of file)...
I'm doing this transform through a windows form with the following code:
XPathDocument myXPathDoc = new XPathDocument(xmlfile);
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(xslfile);
XmlTextWriter myWriter = new XmlTextWriter(xmlexcelfile, null);
myWriter.Formatting = Formatting.Indented;
myWriter.Namespaces = true;
myXslTrans.Transform(myXPathDoc, null, myWriter);
myWriter.Close();
I've tried playing around with the xsl:output standalone="yes/no", as well as omit-xml-declaration="no". I've also tried (in the C#) code adding myWriter.WriteStartDocument(); before transforming but that was not allowed. I have tried searching online for this as well and keep coming back to the standalone="yes" but that isn't working. Is there something I am missing here? Oh and in case you are wondering why I need to have the
<?xml version="1.0"?>
at the top of the resulting file, it's because when opening the xml file with excel, excel doesn't recognize it correctly but if it is included then excel opens it correctly...
You can do this
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />
or something similar to this using XmlWriterSettings
Edit: Added more code. Previous was missing some parts
XmlWriterSettings writerSettings = null;
XsltArgumentList transformationArguments = null;
XslCompiledTransform transformer = null;
MemoryStream memoryStream = null;
XPathDocument xPathDocument = null;
StringBuilder sb = null;
XmlWriter writer = null;
XmlDocument resultXml = null;
try
{
writerSettings = new XmlWriterSettings();
writerSettings.OmitXmlDeclaration = false; // This does it
writerSettings.Indent = true;
transformationArguments = new XsltArgumentList();
transformer = new XslCompiledTransform();
memoryStream = new MemoryStream(System.Text.Encoding.Default.GetBytes(xml.OuterXml));
xPathDocument = new XPathDocument(new StreamReader(memoryStream));
sb = new StringBuilder();
// give the settings to the writer here
writer = XmlWriter.Create(sb, writerSettings);
// this is not mandatory, obviously, just passing parameters to my xslt file
foreach (KeyValuePair<string, object> parameter in parameters)
{
transformationArguments.AddParam(parameter.Key, string.Empty, parameter.Value);
}
using (Stream strm = Assembly.GetExecutingAssembly().GetManifestResourceStream("Lib.XSLTFile1.xslt"))
using (XmlReader reader = XmlReader.Create(strm))
{
transformer.Load(reader);
transformer.Transform(xPathDocument, transformationArguments, writer);
}
resultXml = new XmlDocument();
resultXml.LoadXml(sb.ToString());
// for testing only
File.AppendAllText(#"Your path goes here\result.xml", resultXml.OuterXml);
}
catch (Exception)
{
throw;
}
This is how I do it, but this code is specifically written to create an instance of a XmlDocument. I'm sure you can adapt to your needs.

Getting Variable values out of and XSLT file

I wanted to find out if there is a way of getting a parameter or variable value out of an XSL file. For example, if I have the following:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="username" select ="usertest"/>
<xsl:variable name="password" select ="pass"/>
<!-- ... -->
</xsl:stylesheet>
I would like to read the username and password values from the XSL and use them for authentication. I am using ASP.Net and C# to perform the actual transform on an XML file.
Could someone please share code with me that would allow me to read the XSL variables from ASP.NET/C#. Thanks in advance for the help.
This is easy. XSL files are XML themselves, so you can treat them as such.
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("myfile.xsl");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
XmlNode usrNode = xslDoc.SelectSingleNode("/xsl:stylesheet/xsl:variable[#name='username']", nsMgr);
XmlNode pwdNode = xslDoc.SelectSingleNode("/xsl:stylesheet/xsl:variable[#name='password']", nsMgr);
string usr = usrNode.Attributes["select"].Value;
string pwd = pwdNode.Attributes["select"].Value;
Your question is (edit: was) missing the actual code, but from the description it appears what you are looking for is XPath. XSL will transform one XML document into another XML document, you can then use XPath to query the resulting XML to get out the values that you want.
This Microsoft KB article has information about how to use XPath from C#:
http://support.microsoft.com/kb/308333
Thanks Everone. Here is what finally worked:
Client (asp with vbscript) Used for Testing Purposes:
<%
//Create Object
Set xmlhttp = CreateObject("Microsoft.XMLHTTP")
//Set up the object with the URL
'xmlhttp.open "POST" ,"http://localhost/ASP_Test/receiveXML.asp",False
//Create DOM Object
Set xmldom = CreateObject("Microsoft.XMLDOM")
xmldom.async = false
//Load xls to send over for transform
xmldom.load(Server.MapPath("/ASP_Test/masterdata/test.xsl"))
//Send transform file as DOM object
xmlhttp.send xmldom
%>
//////////////////////////////////////////////////////////////////////////
On the Server Side: (aspx with C#) Accepts xslt and process the transform:
//file path for data xml
String xmlFile = ("\\masterdata\\test.xml");
//file path for transformed xml
String xmlFile2 = ("\\masterdata\\out.xml");
XmlTextReader reader = new XmlTextReader(Request.InputStream);
Transform(xmlFile, reader, xmlFile2);
public static string Transform(string sXmlPath, XmlTextReader xslFileReader, string outFile)
{
try
{
//load the Xml doc
XPathDocument myXPathDoc = new XPathDocument(sXmlPath);
XslCompiledTransform myXslTrans = new XslCompiledTransform();
//load the Xsl
myXslTrans.Load(xslFileReader);
//create the output stream
XmlTextWriter myWriter = new XmlTextWriter
(outFile, null);
//do the actual transform of Xml
myXslTrans.Transform(myXPathDoc, null, myWriter);
myWriter.Close();
return "Done";
}
catch (Exception e)
{
return e.Message;
}
}

What's the property way to transform with XSL without HTML encoding my final output?

So, I am working with .NET. I have an XSL file, XslTransform object in C# that reads in the XSL file and transforms a piece of XML data (manufactured in-house) into HTML.
I notice that my final output has < and > automatically encoded into < and >. Is there any ways I can prevent that from happening? Sometimes I need to bold or italicize my text but it's been unintentionally sanitized.
Your xsl file should have:
an output of html
omit namespaces for all used in the xslt
i.e.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="xsl msxsl">
<xsl:output method="html" indent="no" omit-xml-declaration="yes"/>
<!-- lots -->
</xsl:stylesheet>
And you should ideally use the overloads that accept either a TextWriter or a Stream (not XmlWriter) - i.e. something like:
StringBuilder sb = new StringBuilder();
using (XmlReader reader = XmlReader.Create(source)
using (TextWriter writer = new StringWriter(sb))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("Foo.xslt"); // in reality, you'd want to cache this
xslt.Transform(reader, options.XsltOptions, writer);
}
string html = sb.ToString();
In the xslt, if you really want standalone < / > (i.e. you want it to be malformed for some reason), then you need to disable output escaping:
<xsl:text disable-output-escaping="yes">
Your malformed text here
</xsl:text>
However, in general it is correct to escape the characters.
I have used this in the past to transform XMl documents into HTML strings which is what you need.
public static string TransformXMLDocFromFileHTMLString(string orgXML, string transformFilePath)
{
System.Xml.XmlDocument orgDoc = new System.Xml.XmlDocument();
orgDoc.LoadXml(orgXML);
XmlNode transNode = orgDoc.SelectSingleNode("/");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
XmlWriter writer = XmlWriter.Create(sb, settings);
System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
trans.Load(transformFilePath);
trans.Transform(transNode, writer);
return sb.ToString();
}
(XslTransform is deprecated, according to MSDN. They recommend you switch to XslCompiledTransform.)
Can you post an example of the input/output?

Categories