Use Server.MapPath to load external files - c#

I want to load an XML file which is in D: drive. This is what I used
doc.Load(System.Web.HttpContext.Current.Server.MapPath("/D:/Employee.xml"));
But it gives me an error whenever I try to run my program:
Object reference not set to an instance of an object.
I read it somewhere that Server.MapPath can be used only for webpages or web apps. I made a form in asp.net using c#.
Why am I getting this error?
This is my code:
private void btnRead_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("D:\\Employee.xml");
XmlNode root = doc.DocumentElement;
StringBuilder sb = new StringBuilder();
XmlNodeList nodeList = root.SelectNodes("Employee");
foreach (XmlNode node in nodeList)
{
sb.Append("Name: ");
//Select the text from a single node, “Title” in this case
sb.Append(node.SelectSingleNode("Name").InnerText);
sb.Append("EmpID: ");
sb.Append(node.SelectSingleNode("EmpID").InnerText);
sb.Append("Dept: ");
sb.Append(node.SelectSingleNode("Dept").InnerText);
sb.Append("");
}
System.Web.HttpContext.Current.Response.Write(sb.ToString());
}
I have made a form in VS 2008. Saved the details in an XML file. And now want to display the output.

Why not load directly:
doc.Load("D:\\Employee.xml");

In a desktop application there is not such HttpContext.Current, that's why you get the NullReferenceException. Instead, use
doc.Load("D:/Employee.xml");

Related

How to resolve IOException "file used by another process" while saving XmlDocument?

When I'm trying to save the XML Document I edited the IOException "file used by another process" occured when I try to save that document.
Any ideas how to solve this?
Note: This method is called everytime a new element in the XmlDocument should be written.
public void saveRectangleAsXMLFragment()
{
XmlDocument doc = new XmlDocument();
doc.Load("test.xml");
XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
String input = generateXMLInput();
xmlDocFrag.InnerXml = input;
XmlElement mapElement = doc.DocumentElement;
mapElement.AppendChild(xmlDocFrag);
input = null;
mapElement = null;
xmlDocFrag = null;
doc.Save("test.xml");
}
Its probably one of your other methods, or other part of the code which opened the file and didnt calose it well. Try to search for this kind of problem.
try this if your's application is only access that .xml file
1. Create a Object globally
object lockData = new object();
2.Use than object to lock statement where you save and load xml
lock(lockData )
{
doc.Load("test.xml");
}
lock(lockData )
{
doc.Save("test.xml");
}
From Jon Skeet's related answer (see https://stackoverflow.com/a/8354736/4151626)
There seems to be a bug in XmlDocument.Save()'s treatment of the file stream, where it becomes pinned and is neither Closed() nor Disposed(). By taking direct control of the creation and disposition of the stream outside of the XmlDocument.Save() I was able to get around this halting error.
//e.g.
XmlWriter xw = new XmlWriter.Create("test.xml");
doc.Save(xw);
xw.Close();
xw.Dispose();

Unable to save changes to XML document stored in Sharepoint 2010 Document Library

I am working on a project that requires all SQL connection and query information to be stored in XML files. To make my project configurable, I am trying to create a means to let the user configure his sql connection string information (datasource, catalog, username and password) via a series of text boxes. This input will then be saved to the appropriate node within the SQL document.
I can get the current information from the XML file, and display that information within text boxes for the user's review and correction, but I'm encountering an error when it comes time to save the changes.
Here is the code I'm using to update and save the xml document.
protected void submitBtn_Click(object sender, EventArgs e)
{
SPFile file = methods.web.GetFile("MyXMLFile.xml");
myDoc = new XmlDocument();
byte[] bites = file.OpenBinary();
Stream strm1 = new MemoryStream(bites);
myDoc.Load(strm1);
XmlNode node;
node = myDoc.DocumentElement;
foreach (XmlNode node1 in node.ChildNodes)
{
foreach (XmlNode node2 in node1.ChildNodes)
{
if (node2.Name == "name1")
{
if (node2.InnerText != box1.Text)
{
}
}
if (node2.Name == "name2")
{
if (node2.InnerText != box2.Text)
{
}
}
if (node2.Name == "name3")
{
if (node2.InnerText != box3.Text)
{
node2.InnerText = box3.Text;
}
}
if (node2.Name == "name4")
{
if (node2.InnerText != box4.Text)
{
}
}
}
}
myDoc.Save(strm1);
}
Most of the conditionals are empty at this point because I'm still testing.
The code works great until the last line, as I said. At that point, I get the error "Memory Stream is not expandable." I understand that using a memory stream to update a stored file is incorrect, but I can't figure out the right way to do this.
I've tried to implement the solution given in the similar question at Memory stream is not expandable but that situation is different from mine and so the implementation makes no sense to me. Any clarification would be greatly appreciated.
Using the MemoryStream constructor that takes a byte array as an argument creates a non-resizable instance of a MemoryStream. Since you are making changes to the file (and therefore the underlying bytes), you need a resizable MemoryStream. This can be accomplished by using the parameterless constructor of the MemoryStream class and writing the byte array into the MemoryStream.
Try this:
SPFile file = methods.web.GetFile("MyXMLFile.xml");
myDoc = new XmlDocument();
byte[] bites = file.OpenBinary();
using(MemoryStream strm1 = new MemoryStream()){
strm1.Write(bites, 0, (int)bites.Length);
strm1.Position = 0;
myDoc.Load(strm1);
// all of your edits to the file here
strm1.Position = 0;
// save the file back to disk
using(var fs = new FileStream("FILEPATH",FileMode.Create,FileAccess.ReadWrite)){
myDoc.Save(fs);
}
}
To get the FILEPATH for a Sharepoint file, it'd be something along these lines (I don't have a Sharepoint development environment set up right now):
SPFile file = methods.web.GetFile("MyXMLFile.xml")
var filepath = file.ParentFolder.ServerRelativeUrl + "\\" + file.Name;
Or it might be easier to just use the SaveBinary method of the SPFile class like this:
// same code from above
// all of your edits to the file here
strm1.Position = 0;
// don't use a FileStream, just SaveBinary
file.SaveBinary(strm1);
I didn't test this code, but I've used it in Sharepoint solutions to modify XML (mainly OpenXML) documents in Sharepoint lists. Read this blogpost for more information
You could look into using the XDocument class instead of XmlDocument class.
http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.aspx
I prefer it because of the simplicity and it eliminates having to use Memory Stream.
Edit: You can append to the file like this:
XDocument doc = XDocument.Load('filePath');
doc.Root.Add(
new XElement("An Element Name",
new XAttribute("An Attribute", "Some Value"),
new XElement("Nested Element", "Inner Text"))
);
doc.Save(filePath);
Or you can search for an element and update like this:
doc.Root.Elements("The element").First(m =>
m.Attribute("An Attribute").Value == "Some value to match").SetElementValue(
"The element to change", "Value to set element to");
doc.Save('filePath');

Extract text from XML using C#

I work with XML documents that look like this:
All I need is extract the text between the tags. Since it's being successfully highlighted in black by a common XML editor, I'm assuming I should be able to extract it manually?
So far I've tried the following:
private void Form1_Load(System.Object sender, System.EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("C:\\users\\admin\\desktop\\index.xml");
foreach (object node_loopVariable in doc.ChildNodes) {
node = node_loopVariable;
ProcNode(node);
}
}
private void ProcNode(XmlNode node)
{
Console.WriteLine(node.InnerText);
foreach (XmlNode subNode in node.ChildNodes) {
Console.WriteLine(subNode.InnerText);
}
}
Is that a reliable solution?
Use the XDocument class to read the XML and query it using LINQ to XML.
You can do something like that:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("App_Data/file.xml"));
XmlElement xelNo = xmlDoc.GetElementById("ElementID");
Then you can access the Attributes or Text of this Element;
But to use this you must know the ID of your element.

Reading a *.CSPROJ file in C#

I am attempting to write some code to read in a *.CSPROJ file using C#
The code I have is as follows
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(fullPathName);
XmlNamespaceManager mgr = new XmlNamespaceManager(xmldoc.NameTable);
//mgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
foreach (XmlNode item in xmldoc.SelectNodes("//EmbeddedResource") )
{
string test = item.InnerText.ToString();
}
using the debugger I can see that 'fullPathName" has the correct value and the xmldoc once loaded has the correct contents.
The xmldoc does not have any "Nodes" though, as if the contents are not recognised as XML.
Using a XML editor the *.csproj file validates an XML document.
Where am I going wrong?
Why not use the MSBuild API?
Project project = new Project();
project.Load(fullPathName);
var embeddedResources =
from grp in project.ItemGroups.Cast<BuildItemGroup>()
from item in grp.Cast<BuildItem>()
where item.Name == "EmbeddedResource"
select item;
foreach(BuildItem item in embeddedResources)
{
Console.WriteLine(item.Include); // prints the name of the resource file
}
You need to reference the Microsoft.Build.Engine assembly
You were getting close with your XmlNamespaceManager addition, but weren't using it in the SelectNodes method:
XmlNamespaceManager mgr = new XmlNamespaceManager(xmldoc.NameTable);
mgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
foreach (XmlNode item in xmldoc.SelectNodes("//x:ProjectGuid", mgr))
{
string test = item.InnerText.ToString();
}
(I switched to searching for a different element as my project didn't have any embedded resources)
For completeness here the XDocument version, this simplifies namespace management:
XDocument xmldoc = XDocument.Load(fullPathName);
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
foreach (var resource in xmldoc.Descendants(msbuild + "EmbeddedResource"))
{
string includePath = resource.Attribute("Include").Value;
}

How to add a System.Xml.XmlDocument type to applications state

I am using Asp.net 3.5 and C#
I have to add an XmlDocument to my application state so that everytime my application doesnt access the XML file on my filesystem, I will add this at the Application_Start() function in Global.asax.cs
I am adding this to system state as :
protected void Application_Start(Object sender, EventArgs e)
{
string filePath = Server.MapPath("<path to my XML FILE>");
XmlDocument xmlDoc = new XmlDocument();
try
{
xmlTickerDoc.Load(filePath);
}
finally
{
HttpContext.Current.Application["xmlDoc"] = xmlDoc;
}
}
In this code i try to load the xml file and if the file is not loaded due to any problem then i am wanting a null XmlDocument.
I access this XmlDocument as :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc = HttpContext.Current.Application["xmlDoc"];
the error i get while build is
Cannot implicitly convert type 'object' to 'System.Xml.XmlDocument'. An explicit conversion exists
So How to assign the HttpContext.Current.Application["xmlDoc"] variable as System.Xml.XmlDocument ?
Your problem is here:
xmlDoc = HttpContext.Current.Application["xmlDoc"];
Try
xmlDoc = HttpContext.Current.Application["xmlDoc"] as System.Xml.XmlDocument;
Got the answer after a little googling, a simple one but can be tricky for a PHP developer working on C# (as it was in my case)
well i just had to explicitly cast my application state variable to XmlDocument
that is at place of :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc = HttpContext.Current.Application["xmlDoc"];
I used :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc = (XmlDocument) HttpContext.Current.Application["xmlDoc"];
and it becomes Robust :)
can any one tell me what will be the lifetime of this ApplicationState Variable ?

Categories

Resources