I have a "book.xml" and "book.xslt" the output has been set on text-mode, I don't want to load text file by browser because it is so heavy I need some code to save output text file in hard-drive. How I can implement this kind of transformation by c# ?
This should work:
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(#"c:\book.xslt");
xslt.Transform(#"c:\book.xml", #"c:\output.txt");
Obviously your paths will need to be updated to match your particular scenario, for example:
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Server.MapPath("~/book.xslt"));
xslt.Transform(Server.MapPath("~/book.xml"), Server.MapPath("~/output.txt") );
This will read your XSL file from the root of the site and transform /book.xml and save it to /output.txt.
You can find out more about the System.Xml.Xsl.XslCompiledTransform class here:
System.Xml.Xsl.XslCompiledTransform
Use the System.Xml.Xsl.XslCompiledTransform class.
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(Server.MapPath("~/book.xslt"));
transform.Transform(Server.MapPath("~/book.xml"), Server.MapPath("~/output.xml"));
(Note: this assumed all the documents are stored in the root of the web application)
By using xmwwriter and xdocument like so:
using System.Data;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
public void xmltest(string xmlFilePath, string xslFilePath, string outFilePath)
{
var doc = new XPathDocument(xmlFilePath);
var writer = XmlWriter.Create(outFilePath);
var transform = new XslCompiledTransform();
// The following two lines are only needed if you need scripting.
// Because of security considerations read up on that topic on MSDN first.
var settings = new XsltSettings();
settings.EnableScript = true;
transform.Load(xslFilePath,settings,null);
transform.Transform(doc, writer);
}
More info here:
http://msdn.microsoft.com/en-us/library/14689742.aspx
regards
Related
I'm transforming XML using XSLT sheet. The sheet consists of several files, which are included like this:
<xsl:include href="tokens.xsl"/>
<xsl:include href="glayout.xsl"/>
<xsl:include href="scripts.xsl"/>
<xsl:include href="tables.xsl"/>
<xsl:include href="entities.xsl"/>
<xsl:include href="cmarkup.xsl"/>
The transform code looks like following:
// Load text
var reader = XmlReader.Create(new StringReader(text));
// Load transform
XslCompiledTransform myXslTrans = new XslCompiledTransform();
using (var fs = new FileStream(result.FileName, FileMode.Open, FileAccess.Read))
{
var xmlReader = XmlReader.Create(fs);
myXslTrans.Load(xmlReader);
}
// Perform transformation
MemoryStream ms = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
myXslTrans.Transform(reader, null, writer);
// Recover result to string
ms.Seek(0, SeekOrigin.Begin);
var textReader = new StreamReader(ms);
string transformed = textReader.ReadToEnd();
Transform fails on the include lines. I found out, that I may provide my own resolver to provide missing documents, but since their URLs are relative, I'm getting them appended to current application's folder, like:
D:\Dokumenty\Dev\VS\Dev.Editor\Dev.Editor\bin\Debug\tokens.xsl
There are two dirty solutions:
Cut off the application path to retrieve only file name, then search for the file in original sheet's folder (but what if file had a subfolder, like: Include/tokens.xsl?
Temporarily set current directory to the one in which main sheet resides:
var dir = System.IO.Directory.GetCurrentDirectory();
try
{
System.IO.Directory.SetCurrentDirectory(System.IO.Path.GetDirectoryName(result.FileName));
myXslTrans.Load(xmlReader, null, resolver);
}
finally
{
System.IO.Directory.SetCurrentDirectory(dir);
}
But I don't like this solution either. Is there a way to force the XslCompiledTransform to pass the original URLs to the resolver? Or possibly other, more generic solution to this problem?
If you have a file name or URI with the main stylesheet module then use the overload of the Load method taking a string (https://learn.microsoft.com/en-us/dotnet/api/system.xml.xsl.xslcompiledtransform.load?view=netframework-4.8#System_Xml_Xsl_XslCompiledTransform_Load_System_String_) with e.g. myXslTrans.Load(result.FileName).
I have to generate specific XML data from code.
The XML needs to look like this
<this:declarationIdentifier xmlns:this="demo.org.uk/demo/DeclarationGbIdentifier"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="demo.org.uk/demo/DeclarationGbIdentifier DeclarationGbIdentifier.xsd"
xmlns:nsIdentity="demo.org.uk/demo/DeclarationGbIdentityType">
<this:declarationIdentity>
<nsIdentity:declarationUcr>Hello World</nsIdentity:declarationUcr>
</this:declarationIdentity>
</this:declarationIdentifier>
I have dabbled with XmlSerializer and XDocument but cant get the output to match this exactly
Please help.
I believe this will produce your desired output. There possibly is a simpler way this is just off the cuff to get you started. With the prefixes that you are requiring I would look up XmlDocument and adding namespaces to it to have a better understanding of what the code below is doing. Also what I would do is attempt to acquire the XSD schema file and use the XSD.exe to build a .cs file and then you can move forward with the XmlSerializer. If you move forward with the code below i highly suggest moving off your namespaceuri's into some soft of settings file so you can easily modify them in the event they change.
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("this", "declarationIdentifier", "demo.org.uk/demo/DeclarationGbIdentifier");
root.SetAttribute("xmlns:this", "demo.org.uk/demo/DeclarationGbIdentifier");
root.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
//Just setting an Attribute of xsi:schemaLocation it would always drop the xsi prefix in the xml so this is different to accomodate that
XmlAttribute schemaAtt = doc.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");
schemaAtt.Value = "demo.org.uk/demo/DeclarationGbIdentifier DeclarationGbIdentifier.xsd";
root.Attributes.Append(schemaAtt);
root.SetAttribute("xmlns:nsIdentity", "demo.org.uk/demo/DeclarationGbIdentityType");
doc.AppendChild(root);
XmlElement declarationIdentity = doc.CreateElement("this", "declarationIdentity", "demo.org.uk/demo/DeclarationGbIdentifier");
XmlElement declarationUcr = doc.CreateElement("nsIdentity","declarationUcr","demo.org.uk/demo/DeclarationGbIdentityType");
declarationUcr.InnerText = "Hello World";
declarationIdentity.AppendChild(declarationUcr);
doc.DocumentElement.AppendChild(declarationIdentity);
To output this as a string or dump it off to a file you can use the following operations, I output to a file as well as output to the console in my test app.
using (var stringWriter = new StringWriter())
using (StreamWriter writer = new StreamWriter(#"C:\<Path to File>\testing.xml"))
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
doc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
writer.Write(stringWriter.GetStringBuilder().ToString());
Console.WriteLine(stringWriter.GetStringBuilder().ToString());
}
So I retrieve an XML and XSLT as strings from the DB then used my custom HTML helper called RenderXml to render. The problem is that it is not rendering properly. In my HTML helper is where I do the transformation
public static HtmlString RenderXml(this HtmlHelper helper, string theXml, string theXslt)
{
XDocument xmlTree = XDocument.Parse(xmlPath);
XDocument newTree = new XDocument();
using (XmlWriter writer = newTree.CreateWriter())
{
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XmlReader.Create(new StringReader(xsltPath)));
// Execute the transform and output the results to a writer.
xslt.Transform(xmlTree.CreateReader(), writer);
return new HtmlString(newTree.ToString());
}
}
in my CSHTML I do it like this
<div id="results">#Html.RenderXml(Model.theXmlFile, Model.theXSLFile,)</div>
When I try to return new HtmlString(newTree.ToString()); I get a blank, and when I try to return new HtmlString(writer.ToString()); I get this System.Xml.XmlWellFormedWriter on the page. Do anybody know what I am doing wrong? I got my code from the example here. I have also looked into this one and it works great except I do not use a URI, and when I try to modify it to use XDocument complains about missing parameters, so I stayed away from it. Any ideas why he transformation is not working?
Try moving the line return new HtmlString(newTree.ToString()); outside of the using block:
using (XmlWriter writer = newTree.CreateWriter())
{
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XmlReader.Create(new StringReader(xsltPath)));
// Execute the transform and output the results to a writer.
xslt.Transform(xmlTree.CreateReader(), writer);
}
return new HtmlString(newTree.ToString());
I want to read only the xml used for generating equation, which i obtained by using Paragraph.Range.WordOpenXML. But the section used for the equation is not as per MathML which as i found that the Equation of microsoft is in MathML.
Do I need to use some special converter to get desired xmls or are there any other methods?
You could use the OMML2MML.XSL file (located under %ProgramFiles%\Microsoft Office\Office15)
to transform Microsoft Office MathML (equations) included in a word document into MathML.
The code below shows how to transform the equations in a word document into MathML
using the following steps:
Open the word document using OpenXML SDK (version 2.5).
Create a XslCompiledTransform and load the OMML2MML.XSL file.
Transform the word document by calling the Transform() method
on the created XslCompiledTransform instance.
Output the result of the transform (e.g. print on console or write to file).
I've tested the code below with a simple word document containing two equations, text and pictures.
using System.IO;
using System.Xml;
using System.Xml.Xsl;
using DocumentFormat.OpenXml.Packaging;
public string GetWordDocumentAsMathML(string docFilePath, string officeVersion = "14")
{
string officeML = string.Empty;
using (WordprocessingDocument doc = WordprocessingDocument.Open(docFilePath, false))
{
string wordDocXml = doc.MainDocumentPart.Document.OuterXml;
XslCompiledTransform xslTransform = new XslCompiledTransform();
// The OMML2MML.xsl file is located under
// %ProgramFiles%\Microsoft Office\Office15\
xslTransform.Load(#"c:\Program Files\Microsoft Office\Office" + officeVersion + #"\OMML2MML.XSL");
using (TextReader tr = new StringReader(wordDocXml))
{
// Load the xml of your main document part.
using (XmlReader reader = XmlReader.Create(tr))
{
using (MemoryStream ms = new MemoryStream())
{
XmlWriterSettings settings = xslTransform.OutputSettings.Clone();
// Configure xml writer to omit xml declaration.
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.OmitXmlDeclaration = true;
XmlWriter xw = XmlWriter.Create(ms, settings);
// Transform our OfficeMathML to MathML.
xslTransform.Transform(reader, xw);
ms.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(ms, Encoding.UTF8))
{
officeML = sr.ReadToEnd();
// Console.Out.WriteLine(officeML);
}
}
}
}
}
return officeML;
}
To convert only one single equation (and not the whole word document) just query for the desired Office Math Paragraph (m:oMathPara) and use the OuterXML property of this node.
The code below shows how to query for the first math paragraph:
string mathParagraphXml =
doc.MainDocumentPart.Document.Descendants<DocumentFormat.OpenXml.Math.Paragraph>().First().OuterXml;
Use the returned XML to feed the TextReader.
I've generated a HTML file and the top html declaration looks like this:
<html xml:lang="de-CH" lang="de-CH" xmlns="http://www.w3.org/1999/xhtml">
And then I try to convert it into a different format with this .Net 4 code:
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
XslCompiledTransform proc = new XslCompiledTransform();
proc.Load("Html_to_Sql.xslt");
fsHtmlXml = new FileStream(file.Name, FileMode.Create);
html = XmlReader.Create(file.FullName, settings);
proc.Transform(html, null, fsHtmlXml);
Unfortunately nothing happens as long as I have the xml, lang and xmlns attributes in the HTML.
Why is that?
Your XSLT will need to refer to elements in the http://www.w3.org/1999/xhtml namespace. You haven't posted your XSLT code yet, the the problem most likely lies in that file.
Will this work via XML and XPath
using System;
using System.IO;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
public class TransformXML
{
//This will transform xml document using xslt and produce result xml document
//and display it
public static void Main(string[] args)
{
try
{
XPathDocument myXPathDocument = new XPathDocument(sourceDoc);
XslTransform myXslTransform = new XslTransform();
XmlTextWriter writer = new XmlTextWriter(resultDoc, null);
myXslTransform.Load(xsltDoc);
myXslTransform.Transform(myXPathDocument, null, writer);
writer.Close();
StreamReader stream = new StreamReader (resultDoc);
Console.Write("**This is result document**\n\n");
Console.Write(stream.ReadToEnd());
}
catch (Exception e)
{
Console.WriteLine ("Exception: {0}", e.ToString());
}
}
}
The xmlns attribute specifies the namespace of the XML document. This works in much the same way as namespaces within C#, where two classes with the same name but different namespaces are considered to be completely different classes. Changing the XML namespaces means that your XSLT templates / XPath will not match.