How would I go about editing this XML file:
<?xml version="1.0" encoding="utf-8" ?>
<employees>
<employee id="657434365436543" name="Joe Bloggs" group="Manager" subgroup="Deputy">
<contactDetails>
<homePhone>6535436543</homePhone>
<mobilePhone>654365436543</mobilePhone>
</contactDetails>
<personelFile>
<rightToWork>
<type>Permanent</type>
<expires>Never</expires>
</rightToWork>
<nationalInsurance>6543655543</nationalInsurance>
<startDate>01/09/2009</startDate>
</personelFile>
<holidays>
<entitlements>
<holidays>22</holidays>
<bankHolidays>8</bankHolidays>
<personalDays>1</personalDays>
</entitlements>
<taken>
<holidays>1</holidays>
<bankHolidays>0</bankHolidays>
<personalDays>0</personalDays>
</taken>
<remaining>
<holidays>21</holidays>
<bankHolidays>8</bankHolidays>
<personalDays>1</personalDays>
</remaining>
<booked>
<holidays>22</holidays>
<bankHolidays>8</bankHolidays>
<personalDays>1</personalDays>
</booked>
<remainingtobook>
<holidays>0</holidays>
<bankHolidays>0</bankHolidays>
<personalDays>0</personalDays>
</remainingtobook>
</holidays>
<shifts>
<monday>
<start>0800</start>
<end>1300</end>
</monday>
<tuesday>
<start>0800</start>
<end>1300</end>
</tuesday>
<wednesday>
<start>0800</start>
<end>1300</end>
</wednesday>
<thursday>
<start></start>
<end></end>
</thursday>
<friday>
<start>0800</start>
<end>1300</end>
</friday>
<saturday>
<start>0800</start>
<end>1200</end>
</saturday>
<sunday>
<start></start>
<end></end>
</sunday>
</shifts>
</employee>
</employees>
So far I have the following to select the correct employee from the XML:
XmlTextReader employeesReader = new XmlTextReader("Employees.xml");
var employeesXdoc = XDocument.Load(employeesReader);
var employees = from employee in employeesXdoc.Descendants("employee")
where employee.Attribute("id").Value.ToString() == employeeSelect.Value.ToString()
select new
{
nodes = employee.Nodes()
};
foreach (var employee in employees)
{
// WHAT TO PUT HERE?
}
I'm guessing I've found the right place to insert the editing for the file but then I need to know how to correctly edit it and then save it to the file without losing everything else contained there (otherwise I'd just overwrite the whole file.
Thanks for any help.
A good idea is also to use the xml-serializer-class.
There you can work with usual objects and save it to the xml later :)
http://msdn.microsoft.com/en-us/library/ms733901.aspx
Here is a useful link for updating an XML file without rewriting it in its entirety on each save:
http://support.microsoft.com/kb/301233
the general idea is to use a XMLDocument instead of a XMLTextReader and load your .xml file into the XMLDocument object. then grab the root node and start navigating/querying. once you have found the nodes you wish to edit, make your changes. then when you are done, use XMLDocument.Save(path) to save your chagnes.
IO streams are one way phenoma so you can;t use an reader/writer unless you want to overwrite the existing file.
Related
I've got to create a file with xml header and after that i have to put normal data, smthing like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
Data of the file....
I've already got the code to write it to the file.
Code for that part:
private void setHeader(FileStream output, string nod2, string nod3, string )
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
doc.AppendChild(docNode);
XmlNode header = doc.CreateElement("Header");
doc.AppendChild(header);
XmlNode algorithm = doc.CreateElement("Algorithm");
algorithm.InnerText = "alg";
header.AppendChild(algorithm);
XmlNode node2= doc.CreateElement("nod2");
node2.InnerText = nod2;
header.AppendChild(node2);
XmlNode node3= doc.CreateElement("nod3");
node3.InnerText = nod3;
header.AppendChild(node3);
XmlNode node= doc.CreateElement("node");
header.AppendChild(node);
XmlNode user1 = doc.CreateElement("User");
node.AppendChild(user1);
XmlNode mail = doc.CreateElement("Email");
user1.AppendChild(mail);
XmlNode sessionKey = doc.CreateElement("SessionKey");
user1.AppendChild(sessionKey);
doc.Save(output);
}
It work's pretty well, but when i want to read it with
private void readHeader(FileStream input, out string algorithm)
{
XmlDocument doc = new XmlDocument();
doc.Load(input);
}
I got an error that when the "Data of the file..." starts: "Data on the root level is invalid".
Is there a way to do it with the data after whole xml, or have i to add the data as a node?
This can be done in multiple ways. In comments, you've indicated that the best way is unacceptable for reasons outside the scope of the discussion. For completeness, I'm going to put that one first anyway. Skip down to tl;dr for what I think you'll have to end up doing.
The preferred way to do this is to base64 encode the encrypted data and put it in a CDATA block:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<File>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
<Data><![CDATA[
ICAgIFhtbE5vZGUgYWxnb3JpdGhtID0gZG9jLkNyZWF0ZUVsZW1lbnQoIkFsZ29yaXRobSIpOw0K
ICAgIGFsZ29yaXRobS5Jbm5lclRleHQgPSAiYWxnIjsNCiAgICBoZWFkZXIuQXBwZW5kQ2hpbGQo
YWxnb3JpdGhtKTsNCiAgICBYbWxOb2RlIG5vZGUyPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMiIp
Ow0KICAgIG5vZGUyLklubmVyVGV4dCA9IG5vZDI7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5v
ZGUyKTsNCiAgICBYbWxOb2RlIG5vZGUzPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMyIpOw0KICAg
IG5vZGUzLklubmVyVGV4dCA9IG5vZDM7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5vZGUzKTs=
]]></Data>
</File>
That's the canonical answer to this question.
But you've told me that in your case, a requirement has been imposed that you can't do it that way.
Second choice is MIME (actually, MIME might be the first choice and the above might be the second). But I have a feeling they won't like MIME either.
Third choice, read the file as a string and search for some marker that's inserted between the XML and the binary data, something like a MIME boundary.
tl;dr
If they won't let you add such a marker to the file (and I bet they won't), search for the first occurrence of the substring "</Header>":
var xml = File.ReadAllText(filePath);
var endTag = "</Header>";
var headerXML = xml.Substring(0, xml.IndexOf(endTag) + endTag.Length);
var xdHeader = new XmlDocument();
xdHeader.LoadXml(headerXML);
I tested your code with writing directly to a file, doc.Save(#"c:\temp\test1.xml");
And loading from that file works fine. So there is nothing wrong with your xml document. Check your FileStream. Do you flush and close it properly? Does it have UTF-8 encoding?
What's the input in the node strings. Nothing that is invalid according to xml rules?
After a single root node, only comments and processor instructions can be written to xml. So, you can try to write your data in the comments.
It will look like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
...
</Header>
<!-- your data -->
<!-- another data -->
This method has limitations: your data may not contain -- (double-hyphen) and may not end in -.
But it is better, of course, not to do so.
I need to load a xml file in memory so I can access it several times from different forms.
The xml is in this format:
<Slides>
<Slide>
<Name>Name 1</Name>
<Value>Value 1</Value>
<Type>Type 1</Type>
</Slide>
<Slide>
<Name>Name 2</Name>
<Value>Value 2</Value>
<Type>Type 2</Type>
</Slide>
</Slides>
I don't want to use a database to store the vars. Is there any other method to store the data in memory?
Right now I'm using a txt file for each slide and streamreader, which I'm sure is not the best option.
EDIT:
I added this code, but will I be able to get the slides every time without reading the xml file again?
var slides = from s in XElement.Load("slides.xml").Elements("Slide")
select s;
foreach (var slide in slides)
{
//code
}
You should use the XDocument Load method: http://msdn.microsoft.com/en-us/library/bb343181.aspx
i think it is better to use XDocument than the XmlDocument... but it depends on your requirements...
The XDocument is more memory optimized than the XmlDocument, and i think they both are easy for use (for getting values from the xml)
See the XmlDocument class. The Load() method does what you want.
First you have to save the xml file in your project file or your hard disk.Then only you can load the xml file in code behind.
You can create xml file dynamically.it will be much better.
using System.Xml;
XmlDocument myxml = new XmlDocument();
myxml.Load("D:/sample.xml");//Load you xml file from you disk what you want to load
string element_1 = myxml.GetElementsByTagName("Name")[0].InnerText;
string element_2 = myxml.GetElementsByTagName("Value")[0].InnerText;
string element_3 = myxml.GetElementsByTagName("Value")[0].InnerText;
string element_4 = myxml.GetElementsByTagName("Name")[1].InnerText;
string element_5 = myxml.GetElementsByTagName("Value")[1].InnerText;
string element_6 = myxml.GetElementsByTagName("Value")[1].InnerText;
Try this program it will help you.
I am novice and struggling in some XML operations Like open and Delete. I have done the Add part.
Partys.xml
<?xml version="1.0" encoding="utf-8"?>
<Partys>
<Customers>
<Customer CustomerID="1">
<PersonalName>
<LastName>Baker</LastName>
<FirstName>Eugene</FirstName>
</PersonalName>
<Citizenship>Africa</Citizenship>
</Customer>
<Customer CustomerID="2">
<PersonalName>
<LastName>Baker</LastName>
<FirstName>Eugene</FirstName>
</PersonalName>
<Citizenship>Africa</Citizenship>
</Customer>
</Customers>
</Partys>
Q: I want to open the node detail customer where CustomerID (Attribute) is 1. What is the C# code for this?
Q: I want to delete the node customer where CustomerID (Attribute) is 2. What is the C# code for this?
You could try something like this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Parties.xml");
XmlNode t = xmlDoc.SelectSingleNode("/Partys/Customers/Customer[#CustomerID='2']");
t.ParentNode.RemoveChild(t);
xmlDoc.Save();
Once you have t, you can do whatever you want with it including show it in the Console (by accessing the various properties)
Here, we have deleted the node and saved back to file, but you could do whatever you want with the XmlDocument....
Ok, I have to do the following IN C# ( C Sharp ), I am new to C Sharp programming.
I have got the following ( see below )XML file. It is required from me to select using XPath all coreect nodes in a separate .txt file, and all incorrect nodes as well in a separate .txt file.
The correct nodes need to satisfy the following conditions in XPath:
ResourceCatalog/ Resource
ResourceCatalog / ResourceGroup / Resource
ResourceCatalog ........... ResourceGroup / Resource
This is the original XML file:
<?xml version="1.0" encoding="utf-8"?>
<ResourceCatalog>
<Resource name ="Res1"></Resource>
<Resource>
<Name>Res3</Name>
</Resource>
<Service>
<Resource name ="Res2"></Resource>
<ResourceGroup name="Group2">
<Resource name ="Res4"></Resource>
<Resource>
<Name>Res6</Name>
</Resource>
</ResourceGroup>
</Service>
<ResourceGroup name="Group1">
<ResourceGroup name="Group12">
<Service>
<Resource name ="Res8"></Resource>
</Service>
<Resource name ="Res5"></Resource>
<Resource>
<Name>Res7</Name>
</Resource>
</ResourceGroup>
<Resource name ="Res9"></Resource>
</ResourceGroup>
</ResourceCatalog>
I know this question is old, but i hate to see an SO question i come across go unanswered and since it might benefit someone in the future - you could use an XPath like the following:
//Resource
This will select all nodes in the XML document with the name Resource, which seems to match the criteria outlined in your question. The following is a non-optimal, non-generic approach to solving this problem (since it requires the inverse XPath to be manually generated), but will work:
private static void SortNodes(string xml)
{
const string correctXPath = #"//Resource";
const string incorrectXPath = #"//*[not(contains(name(), 'Resource'))]";
var document = new XmlDocument();
document.LoadXml(xml);
var correctNodes = document.SelectNodes(correctXPath);
var incorrectNodes = document.SelectNodes(incorrectXPath);
foreach (var node in correctNodes)
{
// Put into 'correct' txt file
}
foreach (var node in incorrectNodes)
{
// Put into 'incorrect' txt file
}
}
If your XML file is large you may also be better off using an XmlTextReader, rather than loading the entire document into an XmlDocument structure.
However if i were going to solve this myself, i would use XSLT since all you want to do is transform XML to another text form. Off-hand i don't know the XSLT to use though so you would need to do more research on that. There are plenty of examples online and this is a fairly simple scenario.
ok, so, i have an xml file that looks like this:
<?xml version="1.0"?>
<Users>
<User ID="1">
<nickname>Tom</nickname>
<password>a password</password>
<host>anemail#hello.com</host>
<email>anemail</email>
<isloggedin>false</isloggedin>
<permission>10</permission>
</User>
<User ID="2">
<nickname>ohai</nickname>
<password>sercret</password>
<host>my#host</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
<Users>
now, first, i will have a return of what their ID number is, so, ill have "2".
from that, i will need to go into, and edit the fields in it, and resave the xml.
so basically what i need, is to open the file, find the info for User ID="2", and resave the xml, with DIFFERENT values inside of user 2, without affecting the rest of the document.
examlpe:
<User ID="2">
<nickname>ohai</nickname>
<password>sercret</password>
<host>my#host</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
//do the alterations here, and end up with
<User ID="2">
<nickname>ohai</nickname>
<password>somthing that is different than before</password>
<host>the most current host that they were seen as</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
etc.
Summary:
i need to open a text file, return the information via ID number, edit the information, re-save the file. without affecting anything other than user 2
~Thanks!
There are multiple ways you could do this - this is with an XmlDocument, which works in .NET 1.x and up, and works fine as long as your XML document isn't too long:
// create new XmlDocument and load file
XmlDocument xdoc = new XmlDocument();
xdoc.Load("YourFileName.xml");
// find a <User> node with attribute ID=2
XmlNode userNo2 = xdoc.SelectSingleNode("//User[#ID='2']");
// if found, begin manipulation
if(userNo2 != null)
{
// find the <password> node for the user
XmlNode password = userNo2.SelectSingleNode("password");
if(password != null)
{
// change contents for <password> node
password.InnerText = "somthing that is different than before";
}
// find the <host> node for the user
XmlNode hostNode = userNo2.SelectSingleNode("host");
if(hostNode != null)
{
// change contents for <host> node
hostNode.InnerText = "the most current host that they were seen as";
}
// save changes to a new file (or the old one - up to you)
xdoc.Save("YourFileNameNew.xml");
}
If you're using .NET 3.5 and up, you could also check into Linq-to-XML for a probably even easier way to manipulate your XML document.
Marc
Check out this question, should have your answer using Linq-to-XML. This involves writing out to a Console window, but the theory is the same.
Linq to XML - update/alter the nodes of an XML Document
You may use XmlDocument for this:
var doc = new XmlDocument();
doc.Load("1.xml");
var node = doc.SelectSingleNode(#"//User[#ID='2']");
node.SelectSingleNode("password").InnerText="terces";
doc.Save("1.xml");