Passing XML from XSLT to C# function - c#

I got an XSLT variable resultxml which holds a complete xml. Now I want to save this XML in to a xml File.
I had written some code like this
In XSLT
<xsl:value-of select="XSLTHelper:SaveXML($resultxml)"/>
In C#
public static void SaveXML(string xmls)
{
File.WriteAllText( HttpContext.Current.Server.MapPath("~/App_Data/missing_data.xml"), xmls.ToString());
}
Data saves correctly but not in XML format just a string value. Is there is any way that I can maintain my XML structure and save it in File?

Assuming you pass in some nodes from XSLT and not a string you might want to try whether using
public static void SaveXML(XPathNodeIterator nodes)
{
foreach (XPathNavigator node in nodes)
{
using (XmlWriter xw = XmlWriter.Create(HttpContext.Current.Server.MapPath("~/App_Data/missing_data.xml")))
{
node.WriteSubtree(xw);
}
}
}
instead of public static void SaveXML(string xmls) gives you the result you want. Of course the code I posted that writes to a single file is kind of nonsense if you really passed in several nodes to your function, but assuming you pass in a single node it should write that to the file HttpContext.Current.Server.MapPath("~/App_Data/missing_data.xml").

Related

How to append to a Xml file for each operation?

I am developing a tool to reads a XMl(input) which contains paths to some folders and files and generate a XML(output) based on the information of all files mentioned in the path. I tried the a code which reads the input xml file where i have give path to a certain folder within a certain tag. The tool works perfectly if i have mentioned only one path in the input xml. But on adding another path the previous the previous contents written to the XML(output) generated are overwritten.I have given the code below for the button event which generates the output XML on click and method that writes details to the XML. I an not sure how to append or where to append in the method that i write details to xml. Please help me out.
public bool GenerateReportFile(InputFile inputFile, string xmlfile)\\button clicked to perform operation
{
//try
//{
//
foreach (var folder in inputFile.FolderList)
{
List<string> foldersList = GetSubFolders(folder);
foldersList.Add(folder);
UpdateFileInfomation(foldersList);
SetVariable(folder);
Serialize(xmlfile, typeof(DeploymentInfo), filesInformation);
}
private static void Serialize(string xmlFilePath, Type type, object obj)\\method that writes contents to xml
{
if (obj == null)
return;
if (!Directory.Exists(Path.GetDirectoryName(xmlFilePath)))
Directory.CreateDirectory(Path.GetDirectoryName(xmlFilePath));
try
{
XmlSerializer serializer = new XmlSerializer(type);
TextWriter textWriter = new StreamWriter(xmlFilePath);\\this line creates a new XML file every time. this is where i need to handle things to avoid overwriting for every path mentioned in my input xml but i am unable to
serializer.Serialize(textWriter, obj);
textWriter.Close();
}
catch (Exception ex)
{
throw ex;
}
}
If your intention is to serialize objects of the same type at a single location you can add them to a list and serialize it instead.
Here is a tutorial:
http://www.dotnetperls.com/serialize-list
Edit:
This only works for Binary Serialization, not XML
You would need to rework your functions a bit:
Your GenerateReportFile should generate the list of objects and pass it to your Serialize

Appending inside a parent tag using XmlWriter

I am using this code to write to a xml document. Issue is every time I call this code it overrides previously written Tags element.
However I want to append multiple Tag elements inside the Tags elements. How can I make such sets using XmlWriter?
using (XmlWriter writer = XmlWriter.Create(path))
{
writer.WriteStartElement("Tags");
writer.WriteElementString("Tag", tagName);
writer.WriteEndElement();
}
I found out over the net few solution involving LINQ, with which I am not very good at. So I am looking something without it?
This can be done via Linq Xml by:
public void AddTagToXml(string path, string tag)
{
XDocument doc;
// Load the existing file
if (File.Exists(path)) doc = XDocument.Load(path);
else
{
// Create a new file with the parent node
doc = new XDocument(new XElement("Tags"));
}
doc.Root.Add(new XElement("tag", tag));
doc.Save(path);
}
It's not terribly efficient as the file is opened and saved on each function call, but it covers your requirements.

XmlDocument in WCF Service method not successfully saving to file using the class' save method

Hello and thanks in advance,
I am attempting to take the input from text boxes in a silverlight application and on an event fired by a button click, convert them to an xml string, pass the string and a specified file name to a WCF service call and in that call save the xml to the specifed file(via a string parameter). The code which captures the text into an xml string seems to be successfully working(based on what I see in the variables when debugging) and looks like this:
private void ServerInfoNext_Click(object sender, RoutedEventArgs e)
{
//new RegisterServerGroupObject instance
RegisterServerGroupObject groupInfo= new RegisterServerGroupObject(groupNameTB.Text,1,parentServerNameTB.Text,LeaderNameCB.SelectedItem.ToString());
var serializer = new XmlSerializer(typeof(RegisterServerGroupObject));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
settings.CloseOutput = true;
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb,settings))
{
serializer.Serialize(writer, groupInfo);
writer.Close();
}
//sb now contains the xml string with the information from the serialized class
string contentsString = sb.ToString();
//create instance of XmlWrite service
XMLWriteServiceClient xmlClient = new XMLWriteServiceClient();
xmlClient.WriteXmlToServerCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(xmlClient_WriteXmlToServerCompleted);
xmlClient.WriteXmlToServerAsync("ServerGroups.xml", contentsString);
}
at this point when the variable contents string is passed to the service method, I can see that it has valid xml, as well as within the service method itself, which looks like this:
public class XMLWriteService : IXMLWriteService
{
public void WriteXmlToServer(string filename,string xmlString)
{
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xmlString.ToString());
try
{
xDoc.Save(filename);
}
catch (FileNotFoundException e)
{
Console.WriteLine(e.InnerException.ToString());
}
}
}
The try/catch block is not indicating that the file("ServerGroups.xml") is not found, and I currently have that xml file in the ClientBin of the server side portion of the project. (the .Web side). However, after the method terminates there is no new xml written to the file. Can someone please tell me what I am doing wrong? I don't know why the XmlDocument class instance is not saving its contents to the file. Thanks in advance!
You aren't passing a path, so it's just going to save the file to the current directory of the WCF service process, whatever that happens to be. Either find out what that is, or do a search on your whole server drive for that file name to see where it's saving it. Better yet, call Path.Combine to append a path to the begining of the file name before you save to it. For instance:
xDoc.Save(Path.Combine("C:\\ClientBin", filename));
To answer your question in the comment below, if you want to append the incoming XML data to the data that is already stored in the XML file on the server, that's a bit more involved. It all depends what the format of the XML is. Since you are using serialization, which by default will only allow one object per XML document (because it puts the object name as the root document element, of which there can only be one), then you would have to have a different XML format. For instance, on the server side, you would need to have some kind of root element on the document under which you could keep appending the incoming RegisterServerGroupObject objects. For instance, if your XML file on the server looked like this:
<?xml version="1.0" encoding="utf-8" ?>
<ListOfRegisterServerGroupObject>
</ListOfRegisterServerGroupObject>
Then, you could append the data by inserting new elements within that root element, like this:
<?xml version="1.0" encoding="utf-8" ?>
<ListOfRegisterServerGroupObject>
<RegisterServerGroupObject>
...
</RegisterServerGroupObject>
<RegisterServerGroupObject>
...
</RegisterServerGroupObject>
...
</ListOfRegisterServerGroupObject>
To do this, you would need to first load the XML document, then get the root element, then append the incoming XML as a child element. For instance:
public void WriteXmlToServer(string filename, string xmlString)
{
string filePath = Path.Combine("C:\\ClientBin", filename);
XmlDocument storage = New XmlDocument();
storage.Load(filePath);
XmlDocument incoming = New XmlDocument();
incoming.LoadXml(xmlString);
storage.DocumentElement.AppendChild(incoming.DocumentElement);
storage.Save(filePath);
}
You may need to 'map' the physical path to the output file within the service
string path = HostingEnvironment.MapPath("~/MyPath/MyFile.xml");

i can't write to XML string containing path to file, c# Net 3.5

i got file which contains simple XML structure, to operate on xml i use classes bulit in framework 3.5, for string not containing backslashes everything works fine, but in case strings i try to write contain backslashes final file isn't saved to disk, no exception or any kind of error at all. No matter if i write it as parrameter or as value of node, i even tried replace "\" with "\\" with no succes. What I'm doing wrong?
to create node i use following code
public XmlElement ToXml(XmlDocument docXml){
XmlElement answer = docXml.CreateElement("datafile");
answer.SetAttribute("name", dfName);
answer.SetAttribute("path", dfPath);
answer.SetAttribute("user", dfUser);
answer.SetAttribute("pass", dfPass);
answer.SetAttribute("defalut", isDefault.ToString().ToLower());
return answer;
}
Thanks in advance for any suggestions
Paul
I tried this myself and I have no trouble whatsoever:
class Program
{
static void Main(string[] args)
{
// get a list of files
string[] files = Directory.GetFiles(#"D:\backup");
// create new XML document
XmlDocument xdoc = new XmlDocument();
// add a "root" node
xdoc.AppendChild(xdoc.CreateElement("ListOfFiles"));
foreach (string file in files)
{
xdoc.DocumentElement.AppendChild(CreateXmlElement(xdoc, file));
}
// save file
xdoc.Save(#"D:\filelist.xml");
}
private static XmlElement CreateXmlElement(XmlDocument xmldoc, string filename)
{
XmlElement result = xmldoc.CreateElement("datafile");
result.SetAttribute("name", Path.GetFileName(filename));
result.SetAttribute("path", Path.GetDirectoryName(filename));
result.SetAttribute("fullname", filename);
return result;
}
}
Gives me a nice, clean XML file as a result:
<ListOfFiles>
<datafile name="mse-01-14.zip" path="D:\backup" fullname="D:\backup\mse-01-14.zip" />
<datafile name="Vor_09.iso" path="D:\backup" fullname="D:\backup\Vor_09.iso" />
</ListOfFiles>
Not a single problem at all.
Marc
I am assuming that you are trying to put backslash for the node named "path". You can't do that.
Use CDATA section to put characters that should be ignored by XML parser.
EDIT: It seems "\" is not a reserved character and I was able to edit an existing XML file & put it as below.
And the browser renders it as expected.
<Employees xmlns="http://Employees">
<Employee id="12615" title="Architect">
<!--This is a comment-->
<Name>
<First>Nancy</First>
<Middle>J.</Middle>
<Last>Davolio</Last>
</Name>
<Street>507 - 20th Ave. E. Apt. 2A</Street>
<City>Seattle</City>
<Zip>98122</Zip>
<Country>
<Name test="\abc">U.S.A.\\\\</Name>
</Country>
<Office>5/7682</Office>
<Phone>(206) 555-9857</Phone>
<Photo>Photo.jpg</Photo>
</Employee>
</Employees>
What is the content of the variable that has backslash in it?

How to Update a XML Node?

It is easy to read an XML file and get the exact Node Text, but how do I Update that Node with a new value?
To read:
public static String GetSettings(SettingsType type, SectionType section)
{
XmlTextReader reader = new XmlTextReader(HttpContext.Current.Request.MapPath(APPSETTINGSPATH));
XmlDocument document = new XmlDocument();
document.Load(reader);
XmlNode node = document.SelectSingleNode(
String.Format("/MyRootName/MySubNode/{0}/{1}",
Enum.Parse(typeof(SettingsType), type.ToString()),
Enum.Parse(typeof(SectionType), section.ToString())));
return node.InnerText;
}
to write ...?
public static void SetSettings(SettingsType type, SectionType section, String value)
{
try
{
XmlTextReader reader = new XmlTextReader(HttpContext.Current.Request.MapPath(APPSETTINGSPATH));
XmlDocument document = new XmlDocument();
document.Load(reader);
XmlNode node = document.SelectSingleNode(
String.Format("/MyRootName/MySubNode/{0}/{1}",
Enum.Parse(typeof(SettingsType), type.ToString()),
Enum.Parse(typeof(SectionType), section.ToString())));
node.InnerText = value;
node.Update();
}
catch (Exception ex)
{
throw new Exception("Error:", ex);
}
}
Note the line, node.Update(); does not exist, but that's what I wanted :)
I saw the XmlTextWriter object, but it will write the entire XML to a new file, and I just need to update one value in the original Node, I can save as a new file and then rename the new file into the original name but... it has to be simpler to do this right?
Any of you guys have a sample code on about to do this?
Thank you
You don't need an "update" method - setting the InnerText property updates it. However, it only applies the update in memory. You do need to rewrite the whole file though - you can't just update a small part of it (at least, not without a lot of work and no out-of-the-box support).
XmlDocument.Load has an overload that will take the filename directly so there is no need for the reader.
Similarly when you are done XmlDocument.Save will take a filename to which it will save the document.
The nodeValue property can be used to change the value of a text node.
The following code changes the text node value of the first element:
Example:
xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Easy Cooking";
source: http://www.w3schools.com/DOM/dom_nodes_set.asp
You're updating the node in an in-memory representation of the xml document, AFAIK there's no way to update the node directly in the physical file. You have to dump it all back to a file.

Categories