I'm doing an xslt transform of the xml within an excel file using Saxon where the transform is being done on the .rels xml file within the xlsx file. I currently have a workaround in place where I have unzipped the entire contents of the xlsx file into a seperate folder. However, for simplicity's sake my program takes the xlsx file as it's input, so I was wondering if there was a simpler way for my program to point to the xml within the xlsx file without the need to unzip the contents. I've tried pathing to file.xlsx\_rels\.rels but that doesn't seem to work. The code I'm current using for this input is
String inputFile = "file.xlsx_folder\\_rels\\.rels"
XdmNode input = processor.NewDocumentBuilder().Build(new Uri(inputFile));
but I would like to have that point directly within the xlsx.
Yes there is a simpler way, you don't need to unzip the whole file.
Instead of the file path you've passed as a parameter to the Saxon APIs Build function, pass an XmlReader or Stream instance of the uncompressed part of the xslx file.
The Open static method of System.IO.Packaging.Package can be used to get a Package instance on which you call GetStream to uncompress the part you need and return it as a Stream. Package handles files conforming to the Open Packaging Convention, like Excel's xslx format.
The code below uncompresses the package part to a Stream, uses this to create an XmlReader instance, and finally passes the XmlReader as the parameter to the Build function:
string filename = "c:\\test\\file.xslx";
string partPath = "/_rels/.rels";
Package xpsPackage = Package.Open(fileName, FileMode.Open)
Uri partUri = new Uri(partPath, UriKind.Relative);
PackagePart xpsPart = xpsPackage.GetPart(partUri);
Stream xpsStream = xpsPart.GetStream(FileMode.Open)
XmlReader xmlReader = XmlReader.Create(xpsStream);
XdmNode input = processor.NewDocumentBuilder().Build(xmlReader);
Related
I have a xml file in cmd argument and xsd file in resources. var xsdstring = Recourses.EmployeeSchema; How can i use this xsdstring to validate xml file using xmlDeserlize method. I read a lot of article but can't find solution
I am using http://www.thescarms.com/dotnet/XSLT.aspx to Convert comma delimited data (CSV) to XML using XSLT template.
It uses the foll. 2 lines of .NET code:
XSLT.Load(mstrInputXSLTFile, resolver);
XSLT.Transform(mstrInputCSVFile, mstrOutputXMLFile, resolver);
I am looking for a way in which I can use the string contents (contents of the XSLT, CSV file) instead of files in above 2 methods.. Any help will be usefull.
I am planning to implement this logic in a WCF webservice which will receive the csv string. If there is no workaround then I will have to create temp files based on the values of csv and xsl received. Process the conversion of csv to xml on the server and return the xml output to the client. Then delete the files created above.
If you want to load the input from a string then create an XmlReader over a StringReader over your string e.g.
XslCompiledTransform proc = new XslCompiledTransform();
using (StringReader sr = new StringReader(stringVar))
{
using (XmlReader xr = XmlReader.Create(sr))
{
proc.Load(xr);
}
}
There is no suitable method in XslTransform which does what you want.
However, you could write your own extensions methods (I would call them Parse..), which take content as string, create files in the temporary directory, and load/transform them by the suitable methods.
I am creating an XML file on the fly.
One of it's nodes contains a ZIP file encoded as a BASE64 string.
I then create another ZIP file.
I add this XML file and a few other JPEG files.
I output the file to the browser.
I am unable to open the FINAL ZIP file.
I get: "Windows cannot open the folder. The Compressed(zipped) Folder'c:\path\file.zip' is invalid."
I am able to save my original XML file to the file system.
I can open that XML file, decode the ZIP node and save to the file system.
I am then able to open that Zip file with no problems.
I can create the final ZIP file, OMIT my XML file, and the ZIP file opens no problem.
I seem to only have an issue with I attempt to ZIP an XML file that has a node with ZIP content encoded as a BASE64 string.
Any ideas? Code snipets are below. Heavily edited.
XDocument xDoc = new XDocument();
XDocument xDocReport = new XDocument();
XElement xNodeReport;
using (FileStream fsData = new FileStream(strFullFilePath, FileMode.Open, FileAccess.Read)) {
xDoc = XDocument.Load(fsData);
xNodeReport = xDoc.Element("Data").Element("Reports").Element("Report");
//SNIP
//create XDocument xDocReport
//SNIO
using (MemoryStream zipInMemoryReport = new MemoryStream()) {
using (ZipArchive zipFile = new ZipArchive(zipInMemoryReport, ZipArchiveMode.Update)) {
//Add REPORT to ZIP file
ZipArchiveEntry entryReport = zipFile.CreateEntry("data.xml");
using (StreamWriter writer = new StreamWriter(entryReport.Open())) {
writer.Write(xDocReport.ToString());
} //END USING report entry
}
xNodeReport.Value = System.Convert.ToBase64String(zipInMemoryReport.GetBuffer());
//I am able to write this file to disk and manipulate it no problem.
//File.WriteAllText("c:\\users\\snip\\desktop\\Report.xml",xDoc.ToString());
}
//create ZIP for response
using (MemoryStream zipInMemory = new MemoryStream()) {
using (ZipArchive zipFile = new ZipArchive(zipInMemory, ZipArchiveMode.Update)) {
//Add REPORT to ZIP file
ZipArchiveEntry entryReportWrapper = zipFile.CreateEntry("Report.xml");
//THIS IS THE STEP THAT makes the Zip "invalid". Although i can open and manipulate this source file no problem.
//********
using (StreamWriter writer = new StreamWriter(entryReportWrapper.Open())) {
xDoc.Save(writer);
}
//Add JPEG(s) to report
//Create Charts
if (chkDLSalesPrice.Checked) {chartDownloadSP.SaveImage(entryChartSP.Open(), ChartImageFormat.Jpeg);}
if (chkDLSalesDOM.Checked) {chartDownloadDOM.SaveImage(entryChartDOM.Open(), ChartImageFormat.Jpeg);}
if (chkDLSPLP.Checked) {chartDownloadSPLP.SaveImage(entryChartSPLP.Open(), ChartImageFormat.Jpeg);}
if (chkDLSPLP.Checked) {chartDownloadLP.SaveImage(entryChartLP.Open(), ChartImageFormat.Jpeg);}
} // END USING ziparchive
Response.Clear();
Response.AppendHeader("content-disposition", "attachment; filename=file.zip");
Response.ContentType = "application/zip";
Response.BinaryWrite(zipInMemory.GetBuffer());
Response.End();
Without a good, minimal, complete code example, it's impossible to know for sure what bugs are in the code. But there are at least two apparent errors in the code snippet you posted, one of which could easily be responsible for the "invalid .zip" error:
In the statement writer.Write(xDocReport.ToString());, the variable xDocReport has not been initialized to anything useful, at least not in the code you posted. So you'll get an empty XML document in the archive.
Since the code example is incomplete, it's possible you just omitted from the code example in your question the initialization of that variable to something else. In any case, even if you didn't that would just lead to an empty XML document in the archive, not an invalid archive.
More problematic though…
You are calling GetBuffer() on your MemoryStream objects, instead of ToArray(). You want the latter. The former gets the entire backing buffer for the MemoryStream object, including the uninitialized bytes past the end of the valid stream. Since a valid .zip file includes a CRC value at the end of the file, adding extra data beyond that causes anything trying to read the file as a .zip archive to miss the correct CRC, reading the uninitialized data instead.
Replace your calls to GetBuffer() with calls to ToArray() instead.
If the above does not lead to a solution for your problem, you should edit your post, to provide a better code example.
One last comment: there is no point in initializing a variable like xDoc to an empty XDocument object when you're going to just replace that object with a different one (e.g. by calling XDocument.Load()).
I am serializing an object with the following code, which uses GZip and Xml:
FileStream fs = new FileStream(destinationfolder + "/myFileName.gz",
FileMode.Create, FileAccess.Write);
using (var gz = new GZipStream(fs, CompressionMode.Compress)) {
var serializer = new XmlSerializer(typeof(MyObjectType));
serializer.Serialize(gz, myObject);
}
That works fine, with one single problem: The user can open the .gz file with 7Zip (after setting the file association), but then he can't just doubleclick the shown xml inside the .gz file, since it doesn't have the .xml extension (although the content is actually there, xml formatted and all).
Question is: "How can I serialize XML to a GZipStream so that the .xml extension is saved with the file, inside the .gz archive?" I'm using .NET 4.0.
Thanks for reading.
I have figure out a simple way to solve that. If this way should be considered a hack or a pragmatic and fine solution, is up to each one, I think.
Simply set the GZip filename to myFileName.xml.gz. This actually makes the inner file appear as myFileName.xml (trimming out the .gz extension as before).
I hope this won't break in the future...
I have this xml file: http://www.studiovincent.net/list.xml
I need copy whole content in other xml file.
I tryed this code:
string sourcefile = "http://www.studiovincent.net/list.xml";
string destinationfile = "test.xml";
System.IO.File.Copy(sourcefile, destinationfile);
But not work, because I get this error: URI formats are not supported.
How Can I solve this problem?
File.Copy() does not support the http:// protocol, hence the URI formats are not supported error.
You can work around this by reading in the contents of the page into a string, and then writing it to a file.
WebClient client = new WebClient();
string contents = client.DownloadString("http://www.studiovincent.net/list.xml");
// write contents to test.xml
System.IO.File.WriteAllText ("test.xml", contents);
Note that WriteAllText() will create test.xml if it doesn't exist, and overwrite it if it does. You will also want to wrap the above code in a try / catch block and catch and handle the appropriate excpetions.
I would recommend using WebClient.DownloadFile. Downloading a string and then saving it could cause problems with character set mapping.
WebClient client = new WebClient();
client.DownloadFile("http://www.studiovincent.net/list.xml", "test.xml");
This copies the file directly rather than converting the data to a string, which might do some string conversions (for example, the file is Unicode, and WebClient thinks it's UTF-8) and then copying to a file.