Friends,
My school project is having an xml data file:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>Somewhere</add>
<mobile>0000</mobile>
.
.
.
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
My Windowsform "EditPatients_Load" is able to fetch all info of patient Jhon, and now let's assume that the Admin needs to change some information in the form & resubmit.
Then how to write back all values to Jhon's account in the same xml
file????
I'm not able to makeup the logical code, even if I check the node if (patients.paptient.name = "nameComboBox.text").... how to make sure that I'm writing other values on proper place?
Rgrdz,
Try this:
//string xml =
//#"<patients><patient><regNo>2012/Mar/003</regNo><name>Jhon</name><add>Somewhere
//</add><mobile>0000</mobile><stay>2</stay><costofroom>100</costofroom><total>200</total>
//</patient></patients>";
XDocument xmlDoc = XDocument.Load(#"c:\abc.xml");
var items = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item);
if (items.Count() > 0)
{
var item = items.First();
item.SetElementValue("add", "New New Address");
xmlDoc.Save(#"c:\abc.xml", SaveOptions.None);
}
You can get single element using
var item = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item).FirstOrDefault();
then update it using SetElementValue() method.
//Updated Xml
<?xml version="1.0" encoding="utf-8"?>
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>New Address</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Reference:
Update XML with C# using Linq
I would take the xml serialization/deserialization route to solve this:
http://support.microsoft.com/kb/815813
How to Deserialize XML document
That way you can work with objects and not have to parse xml files manually.
If you're using .NET 3.5 onward you can use the XDocument class like the following. I'm assuming your content is in a .xml file.
XDocument xdoc = XDocument.Load(#"C:\Tmp\test.xml");
//this would ensure you get the right node and set its text content/value
xdoc.Element("patients")
.Element("patient").Element("add").Value = "some new address?";
xdoc.Save(#"C:\Tmp\test.xml");
The file test.xml would change to:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>some new address?</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Related
I have this snippt of XML
<unit class="xxx.xxx.xxx" id="382">
<customId>000</customId>
<description>kg</description>
<key>22452</key>
<Description>Kilogramm</Description>
</unit>
how to get the node 'unit' or parnet of the key element using the value of an element. For instance
i have the value of key element above [22452] and it's Uniqe inside the xml-File.
what i am trying to do getting value of customid [000] of that specific tag.
what i did:
var doc = new XmlDocument();
doc.Load(stream); // stream from xml-file
var key = doc.SelectSingleNode(//key/[text()='" + 22452+ "']"); // that i am not sure about it.
var customId = key.InnerText("customId");
For this kind of query you could either find the node and than navigate to the parent.
Or use XPath:
var unitElemnt = doc.SelectSingleNode("//unit[key = '22452']");
(Assuming I've remembered the XPath to match an element's text content correctly.)
This gets a reference to the <unit> element, by using a relative path to the <key> element in the predicate of the XPath expression.
Generally better to avoid // in XPath for performance, but would need full document structure to do that.
For this you can use Linq to Xml queries.
XElement units = XElement.Load("./Test.xml");
XElement unit = (from item in units.Descendants("unit")
where item.Element("key").Value == "22455"
select item).FirstOrDefault();
string customId = unit.Element("customId").Value;
supposing your xml file look like :
<?xml version="1.0" encoding="utf-8"?>
<units>
<unit class="xxx.xxx.xxx" id="385">
<customId>003</customId>
<description>kg</description>
<key>22455</key>
<Description>Kilogramm</Description>
</unit>
<unit class="xxx.xxx.xxx" id="386">
<customId>004</customId>
<description>kg</description>
<key>22456</key>
<Description>Kilogramm</Description>
</unit>
</units>
for more reading check Microsoft Linq to Xml Docs
I am trying to create a list of user id's from an xml document in C#. Here is my latest try:
string xml = WebexAutomation.LstSummaryUser();
XDocument doc = XDocument.Parse(xml)
var result = doc.Descendants("webExId").Single().Value;
Console.WriteLine(result);
My XML looks like it has multiple users and I am trying to create list of each webExId
<?xml version="1.0" encoding="ISO-8859-1"?>
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:use="http://www.webex.com/schemas/2002/06/service/user">
<serv:header>
<serv:response>
<serv:result>SUCCESS</serv:result>
<serv:gsbStatus>PRIMARY</serv:gsbStatus>
</serv:response>
</serv:header>
<serv:body>
<serv:bodyContent xsi:type="use:lstsummaryUserResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<use:user>
<use:webExId>kkkk</use:webExId>
<use:firstName>kkkk</use:firstName>
<use:lastName>llllll</use:lastName>
<use:email>kkkkkk</use:email>
<use:registrationDate>06/07/2014 01:17:13</use:registrationDate>
<use:active>DEACTIVATED</use:active>
<use:timeZoneID>11</use:timeZoneID>
</use:user>
<use:user>
<use:webExId>jjjj</use:webExId>
<use:firstName>ssss</use:firstName>
<use:lastName>dddd</use:lastName>
<use:email>dfdfdf</use:email>
<use:registrationDate>06/10/2013 12:23:52</use:registrationDate>
<use:active>DEACTIVATED</use:active>
<use:timeZoneID>11</use:timeZoneID>
</use:user>
<use:matchingRecords>
<serv:total>44</serv:total>
<serv:returned>10</serv:returned>
<serv:startFrom>1</serv:startFrom>
</use:matchingRecords>
</serv:bodyContent>
</serv:body>
</serv:message>
Any suggestions?
Try this instead
var webExId = XName.Get("webExId", "http://www.tempuri.org");
var webExIds = doc.Descendants(webExId);
I am trying to load an XML formatted string into my GUI using a TreeView control. However, the XML formated string is in proprietary layout.
The XML formatted string structure will look like this:
<Response>
<Data>
<Settings>
<Setting>
<SettingsXml>
<ScanJobs>
<ScanJobsData>
<Mailboxes>
<Name>user1#abc.com|DB1</Name>
<Value>true</Name>
</Mailboxes>
<Mailboxes>
<Name>user2#abc.com|DB1</Name>
<Value>true</Name>
</Mailboxes>
<Mailboxes>
<Name>user3#abc.com|DB2</Name>
<Value>true</Name>
</Mailboxes>
<Mailboxes>
<Name>user4#abc.com|DB2</Name>
<Value>true</Name>
</Mailboxes>
<Mailboxes>
<Name>user5#abc.com|DB3</Name>
<Value>true</Name>
</Mailboxes>
<Mailboxes>
<Name>user6#abc.com|DB3</Name>
<Value>true</Name>
</Mailboxes>
</ScanJobsData>
</ScanJobs>
</SettingsXml>
</Setting>
</Setting>
</Settings>
</Data>
</Response>
Where inside tags we have a and tags. tag represents the name of the mailbox appended with Database name to which that mail box belongs. For example- user1#abc.com is the name of the mailbox which is associated with Database having name as DB1. Now I am getting the above xml formatted data in a String not as a XML file.
I'd like the output to be structured in TreeView as follows :
+DB1
user1#abc.com
user2#abc.com
+DB2
user3#abc.com
user4#abc.com
+DB3
user5#abc.com
user6#abc.com
I've been searching the web for the past few hours, and none of the results have helped. Some have come close, but perhaps properties won't show up, or node's names won't display, etc.
I'm writing in c# in Visual Studio 2010. Thanks for the help!
Try this:
TreeView treeview = new TreeView();
// Get all the <Name> elements
XDocument doc = XDocument.Parse(xmlAsString);
var mailboxNames = doc.Element("Response").Element("Data").Element("Settings").Element("SettingsXml").Element("ScanJobs").Element("ScanJobsData").Elements("Mailboxes").Select(m => m.Element("Name"));
// Extract the email and db in each <Name> element
foreach (var name in mailboxNames)
{
var namesSplit = name.Value.Split('|');
var email = namesSplit[0];
var db = namesSplit[1];
// Create new db node if it not exists and add the email there
if (!treeview.Nodes.ContainsKey(db))
{
TreeNode[] emails = new TreeNode[] { new TreeNode(email) };
TreeNode node = new TreeNode(db, emails);
treeview.Nodes.Add(node);
}
// If db node already exists, add email to currently existing node
else
{
treeview.Nodes[db].Nodes.Add(email);
}
}
This query will return you sequence of DB TreeNodes with mail nodes already added to them:
XDocument xdoc = XDocument.Load(path_to_xml);
// or XDocument.Parse(xml_string);
var nodes = from m in xdoc.Descendants("Mailboxes")
let name = m.Element("Name").Value.Split('|')
select new {
Mail = name[0],
Db = name[1]
} into md
group md by md.Db into g
select new TreeNode(g.Key,
g.Select(x => new TreeNode(x.Mail)).ToArray());
Then simply
treeView.Nodes.AddRange(nodes.ToArray());
I'm writing an application in C#. I already an .xml file that is not empty and I want to add new values to it, without deleting the existing values.
I have tried this code:
First:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("RootEl");//root
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
this.Close();
Second:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("RootEl");//root-ot
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
xmlNewUser.WriteElementString("Ime", null, txtEnterName.Text);
this.Close();
Third:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
xmlNewUser.WriteElementString("Ime", null, txtEnterName.Text);
this.Close();
I think the problem is that the stream doesn’t know where to put the new value.
some more information: the root element is already entered.
If your .NET version supports it, use LINQ to XML. (Caveat: I'm not an expert, and there's probably a more elegant way to write this.)
// Without error handling
var root = XElement.Load(#"C:\Users\TrueWill\Downloads\Foo.xml");
var product =
(from item in root.Elements("item")
where item.Element("name").Value == "Product1"
select item)
.Single();
product.Add(new XElement("size", "small"));
root.Save(#"C:\Users\TrueWill\Downloads\FooCopy.xml");
My test file (before):
<?xml version="1.0" encoding="utf-8"?>
<test>
<item><name>Product1</name></item>
<item><name>Product2</name></item>
</test>
My test file copy (after) (I copied rather than replacing):
<?xml version="1.0" encoding="utf-8"?>
<test>
<item>
<name>Product1</name>
<size>small</size>
</item>
<item>
<name>Product2</name>
</item>
</test>
When you write XML to a file this way, it always overwrites what was in the file before. If you want to write to it using XmlTextWriter, you would have to copy the current content first, and write the new elements at the proper position. Don't forget that you can't read from and write to the same file at the same time, so you have to use a temporary file and overwrite the original with it. Or you read the whole file into a string first. Or write your result into a string first.
But a better solution might be to use XDocument (or XmlDocument) to load the whole document, modify it and then save it. (Doing this is not a good idea if the XML file is huge.)
Use XmlDocument:
XmlDocument doc = new XmlDocument();
doc.Load("filepath");
XmlNode node = doc["MainNode"]["subnode1"]["subnode2"]; //to fetch the node after which you'd like to add something.
XmlElement stuffToAdd = doc.CreateNode("nodename");
stuffToAdd.InnerText = "the value of your added node";
node.AddChild(stuffToAdd);
doc.Save("filepath");
I'm doing this out of memory, so the names of the methods are aproximate.
As said in another answer, loading big XML files using XmlElement can be costy, because it is fully loaded in memory when you call Load().
Is there a reason you are using XmlTextWriter? I find the LINQ to XML alternatives much easier.
your code would be something like below;
XElement el = new XElement("Zapis");
el.Add(new XElement("Name",txtEnterName.Text))
el.Save(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml")
I have a xml document that has a record set like this.
<document>
<row>
<Pub_Code>OHB-A0011</Pub_Code>
<Sec>16</Sec>
<Pags>20</Pags>
<Copies>1,000</Copies>
<Binding>Saddle Stitch</Binding>
<Tab>No tabs</Tab>
<Qty>0</Qty>
<Cover>Self Cover</Cover>
<Tpgs>0</Tpgs>
</row>
</document>
I have a linq query wrtten this way:
string xml_path = #"D:\Server-Apps\BooksData.xml";
XElement root = XElement.Load(xml_path);
var selected = from myBooks in root.Elements("row") where myBooks.Element("Pub_Code").Value == "OHB-A0011" select myBooks;
foreach (var d in selected)
{
Console.WriteLine("Pub_Code: {0}", d.Element("Pub_Code").Value);
Console.WriteLine("Cover: {0}", d.Element("Cover").Value);
d.SetElementValue("Tpgs", "test");
}
I can read the value find but when I uses d.SetElementValue("Tpgs", "test"); nothing gets update.
the tag is already in the xml file .
If you want to save the updated XML back to the file, you need to do:
root.Save(xml_path);
I added the line t the end of your program and it seems to work correctly.