I am converting xml to html using xslt 3.0 saxon-HE 9.8 library. Using it in c# code.
I am passing xml and xslt file path in input to get it transformed and get output.
Can anyone please let me know how can I pass xml as string and xslt as string as input in c# code for processing it.
Below is my code.
public static string Transform_XML(string param, string inputfile, string xsltfilename)
{
var xslt = new FileInfo(xsltfilename);
var input = new FileInfo(inputfile);
// Compile stylesheet
var processor = new Processor();
var compiler = processor.NewXsltCompiler();
var executable = compiler.Compile(new Uri(xslt.FullName));
XPathDocument doc = new XPathDocument(new StringReader(param));
DocumentBuilder db = processor.NewDocumentBuilder();
XdmNode xml;
using (XmlReader xr = XmlReader.Create(new StringReader(param)))
{
xml = db.Build(xr);
}
// Do transformation to a destination
var destination = new DomDestination();
using (var inputStream = input.OpenRead())
{
var transformer = executable.Load();
transformer.SetParameter(new QName("", "", "user_entry"), xml);
transformer.SetInputStream(inputStream, new Uri(input.DirectoryName));
transformer.Run(destination);
}
return destination.XmlDocument.InnerXml.ToString();
}
Want to pass xml and xslt as string instead of file path.
UPDATE 1
Got the solution for passing xml and xsl as string in c#. Below is the updated code.
private string Transform_XML(string param, string param_name, string inputfile, string xsltfilename)
{
string xslt_input = System.IO.File.ReadAllText(xsltfilename + ".xslt");
string xml_input = System.IO.File.ReadAllText(inputfile + ".xml");
// Compile stylesheet
var processor = new Processor();
var compiler = processor.NewXsltCompiler();
compiler.BaseUri=new Uri(Server.MapPath("/"));
var executable = compiler.Compile(new XmlTextReader(new StringReader(xslt_input)));
XPathDocument doc = new XPathDocument(new StringReader(param));
DocumentBuilder db = processor.NewDocumentBuilder();
XdmNode xml;
using (XmlReader xr = XmlReader.Create(new StringReader(param)))
{
xml = db.Build(xr);
}
//xml input
DocumentBuilder builder = processor.NewDocumentBuilder();
builder.BaseUri= new Uri(Server.MapPath("/"));
MemoryStream ms = new MemoryStream();
StreamWriter tw = new StreamWriter(ms);
tw.Write(xml_input);
tw.Flush();
Stream instr = new MemoryStream(ms.GetBuffer(), 0, (int)ms.Length);
XdmNode input = builder.Build(instr);
// Do transformation to a destination
var destination = new DomDestination();
var transformer = executable.Load();
//Set the parameter with xml value
transformer.SetParameter(new QName("", "", param_name), xml);
// Set the root node of the source document to be the initial context node
transformer.InitialContextNode = input;
transformer.Run(destination);
// Get result
return destination.XmlDocument.InnerXml.ToString();
}
The XsltTransformer has a method SetInputStream() that allows you to supply the input as a stream (which indeed you appear to be using).
This post How do I generate a stream from a string? tells you how to create a stream from a string.
Related
I am fairly new coding with C#. I would like to calculate an IRmark of an xml file saved on my c drive.
The IRmark calculation is based on the HMRC's specification on https://www.gov.uk/government/publications/hmrc-irmark-generic-irmark-specification
I have found a code online that I could use to do this. I do not know how to direct it to read and convert the xml file on the c drive instead. I will appreciate your help. Thank you
Here is the code
public static string GetIRMark(byte[] Xml)
{
string vbLf = "\n";
string vbCrLf = "\r\n";
// Convert Byte array to string
string text = Encoding.UTF8.GetString(Xml);
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml(text);
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("env", doc.DocumentElement.NamespaceURI);
XmlNode Body = doc.SelectSingleNode("//env:Body", ns);
ns.AddNamespace("tax", Body.FirstChild.NextSibling.NamespaceURI);
// Create an XML document of just the body section
XmlDocument xmlBody = new XmlDocument();
xmlBody.PreserveWhitespace = true;
xmlBody.LoadXml(Body.OuterXml);
// Remove any existing IRMark
XmlNode nodeIr = xmlBody.SelectSingleNode("//tax:IRmark", ns);
if (nodeIr != null)
{
nodeIr.ParentNode.RemoveChild(nodeIr);
}
// Normalise the document using C14N (Canonicalisation)
XmlDsigC14NTransform c14n = new XmlDsigC14NTransform();
c14n.LoadInput(xmlBody);
using (Stream S = (Stream)c14n.GetOutput())
{
byte[] Buffer = new byte[S.Length];
// Convert to string and normalise line endings
S.Read(Buffer, 0, (int)S.Length);
text = Encoding.UTF8.GetString(Buffer);
text = text.Replace("
", "");
text = text.Replace(vbCrLf, vbLf);
text = text.Replace(vbCrLf, vbLf);
// Convert the final document back into a byte array
byte[] b = Encoding.UTF8.GetBytes(text);
// Create the SHA-1 hash from the final document
SHA1 SHA = SHA1.Create();
byte[] hash = SHA.ComputeHash(b);
return Convert.ToBase64String(hash);
}
I have tried this code
string text = Encoding.UTF8.GetString(#"c:\myfile.xml");
but I get an error message
I have following code:
XslCompiledTransform transform = new XslCompiledTransform();
XsltArgumentList arguments = new XsltArgumentList();
string txId = SPOZUS_T2S_COMMON.Spozus.GetUniqueInputId;
arguments.AddParam("Id", string.Empty, txId);
foreach (KeyValuePair<string, string> kvp in args)
{
arguments.AddParam(kvp.Key, string.Empty, kvp.Value);
}
using (StringReader sr = new StringReader(xslt))
{
using (XmlReader reader = XmlReader.Create(sr))
{
transform.Load(reader); // load transformation
}
}
XDocument inDoc = new XDocument(_ecpIn.Message); // input document
XDocument outDoc = new XDocument(); // output document
using (XmlReader reader = inDoc.CreateReader())
{
XmlWriter XWriter = outDoc.CreateWriter();
using (XmlWriter writer = XmlWriter.Create(XWriter, transform.OutputSettings))
{
transform.Transform(reader, arguments, writer); // do the transformation
}
}
I have the source document inDoc in utf-8 and I need to replace accentuated chars in the values of text value elements and get rid of those that does not match this pattern ([0-9a-zA-Z-\?:().,'+ ]([0-9a-zA-Z-\?:().,'+ ](/[0-9a-zA-Z-\?:().,'+ ])?)).
Any idea?
I have TextBlock with name XML_View, also I know .xml file location string filename = dlg.FileName;
So I want to show xml n that TextBlock, I found a possible solution here (Display XML in a WPF textbox), it gives as a function, like this:
protected string FormatXml(string xmlString)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
StringBuilder sb = new StringBuilder();
System.IO.TextWriter tr = new System.IO.StringWriter(sb);
XmlTextWriter wr = new XmlTextWriter(tr);
wr.Formatting = Formatting.Indented;
doc.Save(wr);
wr.Close();
return sb.ToString();
}
If I get required string, I might just simply write XML_View.Text = String_xml; or something like this. But I don't know how to get string if I have .xml file and I don't know how to use such a function.
I've modified your function to take as parameter the filename to read your xml from. Make sure the file exists in your bin directory (or you use an absolute path like #"C:\temp\myfile.xml" to resolve).
protected string FormatXml(string xmlFile)
{
XmlDocument doc = new XmlDocument();
FileStream fs = new FileStream(xmlFile, FileMode.Open, FileAccess.Read);
doc.Load(fs);
StringBuilder sb = new StringBuilder();
System.IO.TextWriter tr = new System.IO.StringWriter(sb);
XmlTextWriter wr = new XmlTextWriter(tr);
wr.Formatting = Formatting.Indented;
doc.Save(wr);
wr.Close();
return sb.ToString();
}
You can replace
doc.LoadXml(xmlString);
with
doc.Load(xmlFilePath);
I used this as reference.
Currently I'm using this code to deserialize a file
StreamReader str = new StreamReader(reply);
System.Xml.Serialization.XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(typeof(imginfo));
imginfo res = (imginfo)xSerializer.Deserialize(str);
How should I modify the code if reply is a string and not a path to an xml file?
Basically, you use an XmlReader chained to a StringReader:
imginfo res;
using(var sr = new StringReader(xml)) // "xml" is our string containing xml
using(var xr = XmlReader.Create(sr)) {
res = (imginfo)xSerializer.Deserialize(xr);
}
//... use "res"
or as Anders notes:
imginfo res;
using(var sr = new StringReader(xml)) // "xml" is our string containing xml
res = (imginfo)xSerializer.Deserialize(sr);
}
//... use "res"
Use StringReader instead of StreamReader. No other change needed.
I want to apply an XSLT Stylesheet to an XML Document using C# and write the output to a File.
I found a possible answer here: http://web.archive.org/web/20130329123237/http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=63
From the article:
XPathDocument myXPathDoc = new XPathDocument(myXmlFile) ;
XslTransform myXslTrans = new XslTransform() ;
myXslTrans.Load(myStyleSheet);
XmlTextWriter myWriter = new XmlTextWriter("result.html",null) ;
myXslTrans.Transform(myXPathDoc,null,myWriter) ;
Edit:
But my trusty compiler says, XslTransform is obsolete: Use XslCompiledTransform instead:
XPathDocument myXPathDoc = new XPathDocument(myXmlFile) ;
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(myStyleSheet);
XmlTextWriter myWriter = new XmlTextWriter("result.html",null);
myXslTrans.Transform(myXPathDoc,null,myWriter);
Based on Daren's excellent answer, note that this code can be shortened significantly by using the appropriate XslCompiledTransform.Transform overload:
var myXslTrans = new XslCompiledTransform();
myXslTrans.Load("stylesheet.xsl");
myXslTrans.Transform("source.xml", "result.html");
(Sorry for posing this as an answer, but the code block support in comments is rather limited.)
In VB.NET, you don't even need a variable:
With New XslCompiledTransform()
.Load("stylesheet.xsl")
.Transform("source.xml", "result.html")
End With
Here is a tutorial about how to do XSL Transformations in C# on MSDN:
http://support.microsoft.com/kb/307322/en-us/
and here how to write files:
http://support.microsoft.com/kb/816149/en-us
just as a side note: if you want to do validation too here is another tutorial (for DTD, XDR, and XSD (=Schema)):
http://support.microsoft.com/kb/307379/en-us/
i added this just to provide some more information.
This might help you
public static string TransformDocument(string doc, string stylesheetPath)
{
Func<string,XmlDocument> GetXmlDocument = (xmlContent) =>
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlContent);
return xmlDocument;
};
try
{
var document = GetXmlDocument(doc);
var style = GetXmlDocument(File.ReadAllText(stylesheetPath));
System.Xml.Xsl.XslCompiledTransform transform = new System.Xml.Xsl.XslCompiledTransform();
transform.Load(style); // compiled stylesheet
System.IO.StringWriter writer = new System.IO.StringWriter();
XmlReader xmlReadB = new XmlTextReader(new StringReader(document.DocumentElement.OuterXml));
transform.Transform(xmlReadB, null, writer);
return writer.ToString();
}
catch (Exception ex)
{
throw ex;
}
}
I would like to share this small piece of code which reads from Database and transforms using XSLT. On the top I also have used xslt-extensions which makes it little different than others.
Note: This is just a draft code and may need cleanup before using in production.
var schema = XDocument.Load(XsltPath);
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (var command = new SqlCommand(Sql, connection))
{
var reader = command.ExecuteReader();
var dt = new DataTable(SourceNode);
dt.Load(reader);
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine;
using (var stringWriter = new StringWriter())
{
dt.WriteXml(stringWriter, true);
xml += stringWriter.GetStringBuilder().ToString();
}
XDocument transformedXml = new XDocument();
var xsltArgumentList = new XsltArgumentList();
xsltArgumentList.AddExtensionObject("urn:xslt-extensions", new XsltExtensions());
using (XmlWriter writer = transformedXml.CreateWriter())
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(schema.CreateReader());
xslt.Transform(XmlReader.Create(new StringReader(xml)), xsltArgumentList, writer);
}
var result = transformedXml.ToString();
}
}
XsltPath is path to your xslt file.
ConnectionString constant is pointing to your database.
Sql is your query.
SourceNode is node of each record in source xml.
Now the interesting part, please note the use of urn:xslt-extensions and new XsltExtensions() in above code. You can use this if need some complex computation which may not be possible in xslt. Following is a simple method to format date.
public class XsltExtensions
{
public string FormatDate(string dateString, string format)
{
DateTime date;
if (DateTime.TryParse(dateString, out date))
return date.ToString(format);
return dateString;
}
}
In XSLT file you can use it as below;
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="urn:xslt-extensions">
...
<myTag><xsl:value-of select="ext:FormatDate(record_date, 'yyyy-MM-dd')"/></myTag>
...
</xsl:stylesheet>