how to save xmldocument to a stream - c#

I've already written code to parse my xml file with an XmlReader so I don't want to rewrite it. I've now added encryption to the program. I have encrypt() and decrypt() functions which take an xml document and the encryption algorithm. I have a function that uses an xml reader to parse the file but now with the xml document I'm not sure how to create the xmlreader.
The question is how to save my xml document to a stream. I'm sure it's simple but I don't know anything about streams.
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(filep);
Decrypt(doc, key);
Stream tempStream = null;
doc.Save(tempStream); // <--- the problem is here I think
using (XmlReader reader = XmlReader.Create(tempStream))
{
while (reader.Read())
{ parsing code....... } }

You can try with MemoryStream class
XmlDocument xmlDoc = new XmlDocument( );
MemoryStream xmlStream = new MemoryStream( );
xmlDoc.Save( xmlStream );
xmlStream.Flush();//Adjust this if you want read your data
xmlStream.Position = 0;
//Define here your reading

Writing to a file:
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<FTPSessionOptionInfo><HostName>ftp.badboymedia.ca</HostName></FTPSessionOptionInfo>");
using (StreamWriter fs = new StreamWriter("test.xml"))
{
fs.Write(doc.InnerXml);
}
}

I realize this is an old question, but thought it worth adding a method from this nice little blog post. This edges out some less performant methods.
private static XDocument DocumentToXDocumentReader(XmlDocument doc)
{
return XDocument.Load(new XmlNodeReader(doc));
}

try this
XmlDocument document= new XmlDocument( );
string pathTmp = "d:\somepath";
using( FileStream fs = new FileStream( pathTmp, FileMode.CreateNew ))
{
document.Save(pathTmp);
fs.Flush();
}

Related

Editing a XFA PDF with iText (Editing only a field within a node)

Ok so I'm having to programmatically fill out an XFA PDF using C#. I've been able to successfully extract the XML structure of the PDF. However, I'm running into issues using the AcroFields.Xfa.FillXfaForm(sourceXML) calls.
Essentially what is happening is this: I am taking the ENTIRE XML tree, editing the fields within the XML and then attempting to edit the form fields with the new XML. I end up with a PDF stripped of all AcroForm fields, without the new input added. HOWEVER when I parse this edited PDF and extract the XML tree I see that my edits have been preserved.
The security settings for this particular XFA PDF allow form fields to be edited however I am being forced to use PdfReader.unethicalreading = true; with my current set up (which is why I believe the form fields are being stripped out). I believe that the XFA PDF is taking my XML edits as a full on edit to the format of the document itself.
Here is my code so far:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(#"E:\XMLOutPut\outPutTest.xml");
file.WriteLine(ReadFileNames());
file.Close();
using (FileStream existingPdf = new FileStream(#"E:\ORIGINAL.pdf", FileMode.Open))
{
using (PdfReader pdfReader = new PdfReader(existingPdf))
{
using (FileStream sourceXML = new FileStream(#"E:\XMLOutPut\outPutTest.xml", FileMode.Open))
{
using (FileStream targetPdf = new FileStream(#"E:\ORIGINAL.pdf", FileMode.Open))
{
PdfReader.unethicalreading = true;
PdfStamper stamper = new PdfStamper(pdfReader, targetPdf,'\0', true);
stamper.AcroFields.Xfa.FillXfaForm(sourceXML);
stamper.Close();
}
}
}
}
}
public static string ReadFileNames()
{
string SRC = #"E:\ORIGINAL.pdf";
using (PdfReader reader = new PdfReader(SRC))
{
return ReadXFA(reader);
}
}
public static string ReadXFA(PdfReader reader)
{
XfaForm xfa = new XfaForm(reader);
XmlDocument document = xfa.DomDocument;
reader.Close();
if (!string.IsNullOrEmpty(document.DocumentElement.NamespaceURI))
{
document.DocumentElement.SetAttribute("xmlns", "");
XmlDocument newDoc = new XmlDocument();
newDoc.LoadXml(document.OuterXml);
document = newDoc;
}
var sb = new StringBuilder(4000);
var Xsettings = new XmlWriterSettings() { Indent = true };
using (var wrtier = XmlWriter.Create(sb, Xsettings))
{
document.WriteTo(wrtier);
}
return sb.ToString();
}
}
}
I am starting to believe that I have to somehow iterate through the XML and pull out however many fields I'd like to edit and do it that way??
Any help would be greatly appreciated.
Kind regards.
This is currently not possible using iText. You'll need to extract the XFA from the file (you can use iText to do this) and then traverse the XFA structure to make the edits, which you'll have to do with another tool, and then re-insert the XFA into the PDF, which can be done using iText.
static void Main(string[] args)
{
using (FileStream existingPdf = new FileStream(SRC, FileMode.Open))
using (PdfReader pdfReader = new PdfReader(existingPdf))
using (FileStream targetPdf = new FileStream(Target, FileMode.Create))
{
PdfReader.unethicalreading = true;
using (PdfStamper stamper = new PdfStamper(pdfReader, targetPdf, '\0', true))
{
XfaForm form = new XfaForm(pdfReader);
XDocument xdoc = form.DomDocument.ToXDocument();
var nodeElements = from nodeElement in xdoc.Descendants("form1").Descendants("A1")
select nodeElement;
foreach (XElement singleNodeElement in nodeElements)
{
if (singleNodeElement.Name == "A1")
{
singleNodeElement.Value = "LOLGG";
}
}
XmlDocument xmlDoc = xdoc.ToXmlDocument();
XmlNamespaceManager namespaces = new XmlNamespaceManager(xmlDoc.NameTable);
namespaces.AddNamespace("xfa", "http://www.xfa.org/schema/xfa-data/1.0/");
XmlNode baseNode = xmlDoc.SelectSingleNode("//xfa:datasets", namespaces);
stamper.AcroFields.Xfa.FillXfaForm(baseNode);
}
}
}
}
public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using (var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
Alrighty folks so it is possible to do this with iText in addition to Linq and Xml.Linq, as the code example shows above.
In order to make this possible we had to take an XMLDocument and convert it to an XDocument and then use Linq to traverse the nodes. Once we were able to get the correct nodes we had to add a namespace to correctly identify the prefix. We then had to transfer the XDoc format back to an XMLDoc format in order to use the FillXfaForm from iText.

Packagepart copy to file or to memory

I want to extract a xlsx file to get the sheet1.xml file. Now I am struggling with the package and PackagePart. I think the most obvious way is to read that particular file and copy the content to the XmlDocument
This is what i have this far:
XmlDocument doc = new XmlDocument();
using (Package package = ZipPackage.Open(xlsFile, FileMode.Open, FileAccess.Read))
{
foreach (PackagePart part in package.GetParts())
{
var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/')));
var targetDir = target.Remove(target.LastIndexOf('\\'));
if (!Directory.Exists(targetDir))
Directory.CreateDirectory(targetDir);
using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
{
FileStream targetFile = File.OpenWrite(target);
byte[] bytes = new byte[source.Length];
source.Read(bytes, 0, (int)source.Length);
source.Close();
//source.CopyTo(targetFile);
//doc.Load(source.Write());
//targetFile.Close();
}
}
}
I am using .net 3,5 so I cannot use the Stream source.CopyTo methods.
I would like to copy the contents of the Sheet1.xml to the doc of the XmlDocument class..
Thanks!
Paul
You can use XmlDocument.Load overload which takes a Stream:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(part.GetStream(FileMode.Open, FileAccess.Read));
Once loaded, you then can use XmlDocument.Save:
xmlDoc.Save(target);

C# XSLT in memory transformation

I am currently running a live 'in-memory' XSLT transformation using the following code
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(DS.GetXml());
XslCompiledTransform XsltTranformation = new XslCompiledTransform();
XsltTranformation.Load(#"C:\Users\maskew\Desktop\XSLTMapping.xsl");
Stream XmlStream = new MemoryStream();
XmlDoc.Save(XmlStream); //Stream is still blank after this line
XmlReader XmlRdr = XmlReader.Create(XmlStream);
MemoryStream stm = new MemoryStream();
XsltTranformation.Transform(XmlRdr, null, stm);
stm.Position = 1;
StreamReader sr = new StreamReader(stm);
string Output = sr.ReadToEnd();
Output = Output.Substring(2);
XmlDoc.LoadXml(Output);
XmlWriter XmlWrtr = XmlWriter.Create(#"C:\Users\maskew\Desktop\XmlMapping.xml");
XmlDoc.WriteTo(XmlWrtr);
XmlWrtr.Flush();
XmlWrtr.Close();
However, when I move the file from XmlDocument to MemoryStream in line 6 the stream contains nothing when checked and thus stopping the whole program from running.
Does anyone have any idea why this would be occuring?
UPDATED: The stream is containing information now, however the XmlReader object is receiving none of it still.
Try a simplyfying
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(DS.GetXml());
// Create a writer for writing the transformed file.
XmlWriter writer = XmlWriter.Create(#"C:\Users\maskew\Desktop\XmlMapping.xml");
// Create and load the transform with script execution enabled.
XslCompiledTransform transform = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
transform.Load(#"C:\Users\maskew\Desktop\XSLTMapping.xsl", settings, null);
// Execute the transformation.
transform.Transform(xmlDoc, writer);
Try flushing and resetting the stream:
XmlDoc.Save(XmlStream);
XmlStream.Flush();
XmlStream.Position = 0;
XmlReader XmlRdr = XmlReader.Create(XmlStream);
Stream XmlStream = new MemoryStream();
How there can be something in it ? You are constructing an empty memoryStream...
EDIT :
You should try to clarify it by using the 'using' instruction (http://msdn.microsoft.com/fr-fr/library/yh598w02). Basically, class like StreamReader, MemeryStream, etc.. implement the IDisposable interface. If you wrap them with using, it will dispose the object automatically for you.

c# create xml from byte array

i have xml what i get as byte array, whats the best way to get the xml string out of it? I was tryng to use xmltextreader and memorystream but with no success..
XmlDocument doc = new XmlDocument();
string xml = Encoding.UTF8.GetString(buffer);
doc.LoadXml(xml);
OR
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream(buffer);
doc.Load(ms);
This assumes your data has UTF8 encoding which is the usual for XML. Also buffer here is the byte array.
Assuming your xml is in the default 'UTF8' encoding., you could do something like this;
string xml = System.Text.UTF8Encoding.UTF8.GetString(bytes);
System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument().LoadXml(xml);
Or this;
XmlDocument doc = new XmlDocument();
using (MemoryStream ms = new MemoryStream(buffer))
{
doc.Load(ms);
}
Based on the Encoding, you can do
string xmlString = System.Text.UTF8Encoding.UTF8.GetString(bytes);
and use the string
XmlTextReader reader = new XmlTextReader(new StringReader(xmlString));
Take a look at the System.Text.Encoding.UTF8 class. It should let you convert youre byte array into a UTF8 string.

How to Convert a StreamReader into an XMLReader object in .Net 2.0/C#

Here's a quick question I've been banging my head against today.
I'm trying to convert a .Net dataset into an XML stream, transform it with an xsl file in memory, then output the result to a new XML file.
Here's the current solution:
string transformXML = #"pathToXslDocument";
XmlDocument originalXml = new XmlDocument();
XmlDocument transformedXml = new XmlDocument();
XslCompiledTransform transformer = new XslCompiledTransform();
DataSet ds = new DataSet();
string filepath;
originalXml.LoadXml(ds.GetXml()); //data loaded prior
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
transformer.Load(transformXML);
transformer.Transform(originalXml, writer); //no need to select the node
transformedXml.LoadXml(sb.ToString());
transformedXml.Save(filepath);
writer.Close();
Here's the original code:
BufferedStream stream = new BufferedStream(new MemoryStream());
DataSet ds = new DataSet();
da.Fill(ds);
ds.WriteXml(stream);
StreamReader sr = new StreamReader(stream, true);
stream.Position = 0; //I'm not certain if this is necessary, but for the StreamReader to read the text the position must be reset.
XmlReader reader = XmlReader.Create(sr, null); //Problem is created here, the XmlReader is created with none of the data from the StreamReader
XslCompiledTransform transformer = new XslCompiledTransform();
transformer.Load(#"<path to xsl file>");
transformer.Transform(reader, null, writer); //Exception is thrown here, though the problem originates from the XmlReader.Create(sr, null)
For some reason in the transformer.Transform method, the reader has no root node, in fact the reader isn't reading anything from the StreamReader.
My questions is what is wrong with this code? Secondarily, is there a better way to convert/transform/store a dataset into XML?
Edit: Both answers were helpful and technically aku's was closer. However I am leaning towards a solution that more closely resembles Longhorn's after trying both solutions.
I'm not sure but it seems that you didn't reset position in stream before passing it to XmlReader. Try to seek at the beginning of your stream before trying to read from it. Also it may be necessary to close\flush stream after you wrote some data to it.
EDIT:
Just tried following code and it worked perfectly:
BufferedStream stream = new BufferedStream(new MemoryStream());
stream.Write(Encoding.ASCII.GetBytes("<xml>foo</xml>"), 0, "<xml>foo</xml>".Length);
stream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(stream);
XmlReader reader = XmlReader.Create(sr);
while (reader.Read())
{
Console.WriteLine(reader.Value);
}
stream.Close();
You must select the root node. This doesn't use Datasets, but I use this function everyday and it works great.
System.Xml.XmlDocument orgDoc = new System.Xml.XmlDocument();
orgDoc.LoadXml(orgXML);
// MUST SELECT THE ROOT NODE
XmlNode transNode = orgDoc.SelectSingleNode("/");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
System.IO.StringReader stream = new System.IO.StringReader(transformXML);
XmlReader reader = XmlReader.Create(stream);
System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
trans.Load(reader);
trans.Transform(transNode, writer);
XmlDocument doc = new XmlDocument();
doc.LoadXml(sb.ToString());
return doc;
please look it and use..
using (MemoryStream memStream = new MemoryStream())
{
memStream.Write(Encoding.UTF8.GetBytes(xmlBody), 0, xmlBody.Length);
memStream.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(memStream))
{
// xml reader setting.
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings()
{
IgnoreComments = true,
IgnoreWhitespace = true,
};
// xml reader create.
using (XmlReader xmlReader = XmlReader.Create(reader, xmlReaderSettings))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LoginInfo));
myObject = (LoginInfo)xmlSerializer.Deserialize(xmlReader);
}
}
}

Categories