How to get attributes from XML in C# - c#

I am getting output xml format in that can able to access appointment-nbr, but I am not able to eqid. How can I get slot-start,slot-end,eqid.
> <appointment-nbr>494</appointment-nbr> <slot
> slot-start="2018-07-16T12:31:00" slot-end="2018-07-16T13:00:00" />
> <appointment requires-xray="false" /> <container eqid="ASWU2705080" />
This is my code:
foreach (XmlNode node in appointmentsresponce){
XmlElement flightEle = (XmlElement)node;
XmlNodeList appointmentnbr = flightEle.GetElementsByTagName("appointment-nbr");
XmlNodeList containerNodeList = flightEle.GetElementsByTagName("container");
}

Try (I'm guessing a bit since you didn't post the full data):
foreach (XElement level1Element in XElement.Load(#"your_file.xml").Elements("appointment-nbr"))
{
foreach (XElement level2Element in level1Element.Elements("slot"))
{
Console.WriteLine(level1Element.Attribute("slot-start").Value);
}
}

Simple call GetAttribute("AttributeName") on your XmlElement
So:
var slotXml = appointmentsresponce.SelectSingleNode("//slot")
var startAttr = slotXml.GetAttribute("slot-start")
var endAttr = slotXml.GetAttribute("slot-end")
var containerXml = appointmentsresponce.SelectSingleNode("//container ")
var eqidAttr = containerXml .GetAttribute("eqid")

Related

Linq to XML Find a an attribute and return seperate attribute value

<?xml version="1.0" ?>
<aliasSection>
<aliases>
<clear />
<add
name="MAIN"
server="JAG8MTO\SQLEXPRESS"
database="RMain"
trustedConnection="false" />
<add
name="DEMO"
server="JAG8MTO\SQLEXPRESS"
database="RDemo"
trustedConnection="false" />
</aliases>
</aliasSection>
In the above xml doc I need to search for an alias name then return the server and database attributes.
This is my first time working with xml docs and I'm having a hard time wrapping my head around it.
So far I have this, I can find the aliases section but I'm at a loss have to proceed from here.
public void Read(string fileName)
{
XDocument doc = XDocument.Load(fileName);
foreach (XElement el in doc.Root.Elements())
{
foreach (XAttribute attr in el.Attributes())
if (attr.ToString() == "aliases")
{
foreach (XElement element in el.Elements())
listBox1.Items.Add(element.Name + " " + element.Value);
foreach (XAttribute attrib in el.Attributes())
listBox1.Items.Add(attrib.Value);
}
}
}
aliases is element, not attribute
var document = XDocument.Load(fileName);
var data =
document.Descendants("aliases") // Select all <aliases> elements
.SelectMany(alias => alias.Elements("add")) // select all <add> elements
.Select(add => new
{
Name = add.Attribute("name").Value
Server = add.Attribute("server").Value
})
.ToList();
listBox1.Items.AddRange(data);
data will contain selected values of all <add> elements.
foreach (var item in data)
{
Console.WriteLine($"Name: {item.Name}, Server: {item.Server}");
}
// Load the xml into XElement
XDocument doc = XDocument.Load("F:\\db.xml",LoadOptions.None);
// Search through descendants and
// find one with name as MAIN
XElement result = doc.Descendants("add")
.FirstOrDefault(y => y.Attribute("name") != null &&
y.Attribute("name").Value == "MAIN");
// Get the values if valid element is found
if(result != null)
{
string server = (result.Attribute("server") != null) ? result.Attribute("server").Value : string.Empty;
string database = (result.Attribute("database") != null) ? result.Attribute("database").Value : string.Empty;
}

read xml document and update all fields c#

i'm trying to read xml file and update all it's value my xml was
<adf>
<prospect>
<requestdate>2015-10-29 07-38-22</requestdate>
<id sequence="1" source="admin.ss.com">admin.ss.com</id>
<vehicle interest="buy" status="">
<id sequence="1" source=""></id>
<year></year>
<make></make>
<model>camry</model>
<vin></vin>
<stock></stock>
<trim></trim>
</vehicle>
<customer>
<contact primarycontact="1">
<name part="first">Jessica</name>
<name part="last">Sonntag</name>
<email>js#test.com</email>
<phone type="phone" time="day">555-585-5555</phone>
<address>
<street line="1"></street>
<city></city>
<regioncode></regioncode>
<postalcode></postalcode>
<country></country>
</address>
</contact>
<comments>Vehicle Year: 2011 Comments: </comments>
</customer>
<provider>
<name part="full">ST</name>
<service> Engine Marketing</service>
<phone>1-866-572-3952</phone>
</provider>
</prospect>
</adf>
so i select node like below
var items = (from item in xmlDoc.Descendants("requestdate")
select item).ToList();
then i can update only requestdata tag value so do i have to repeat same for all tags or is there any good way to accomplish this.
Regards
There is an easy way to do this. This one is a hidden gem. Most people may not know this. This feature came in VS2013 and it's called "Paste XML as Classes."
Save your xml (Ex: MyXml.XML)
Create a new Console project
Open the Xml in Visual studio
Copy All contents of the xml (Ctl+A, Ctl + C)
Add a new class to your project. You can give any name you like.
Go to Edit>Paste Special>Paste XML as classes.
Add another class to your project. Then add below two methods to that class.
public static string Serialise<T>(T serialisableObject)
{
var doc = new XmlDocument();
using (var stream = new StringWriter())
{
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter xmlWriter = XmlWriter.Create(stream, settings);
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
var xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(xmlWriter, serialisableObject, ns);
doc.LoadXml(stream.ToString());
}
return doc.InnerXml;
}
public static T Deserialise<T>(string xml)
{
T list;
using (var reader = new StringReader(xml))
{
var serialiser = new XmlSerializer(typeof(T));
list = (T)serialiser.Deserialize(reader);
}
return list;
}
Then in your console applications Main method; add this.
var myObj = new adf();
myObj.prospect = new adfProspect();
myObj.prospect.customer = new adfProspectCustomer(){comments = "dgsrtetetete"};
//populate all fields.....
var xml = MySerializer.Serialise(myObj);
File.WriteAllText(#"C:\myNewXml.xml", xml);
That's it. Same way now you can deserialise an xml object in to your class.
Try the XmlSerializer class: https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=vs.110).aspx If you serialize/deserialize the xml then up dating is trivial.
If you wanted to change every phone number to "0123456789" you could do something like:
var xDoc = XDocument.Load("document.xml");
var results = from phone in xDoc.Descendants("phone") select phone;
foreach (XElement result in results)
{
element.SetValue("0123456789");
}
i have came up with solution with support two extension method i'm iterating all nodes and update.(since my xml is not too big or complicated this one would be a good solution)
with help of these two extension methods
public static void IterateThroughAllNodes(this XmlDocument doc, Action<XmlNode> elementVisitor)
{
if (doc != null && elementVisitor != null)
{
foreach (XmlNode node in doc.ChildNodes)
{
DoIterateNode(node, elementVisitor);
}
}
}
public static void IterateThrough(this XmlNodeList nodes, Action<XmlNode> elementVisitor)
{
if (nodes != null && elementVisitor != null)
{
foreach (XmlNode node in nodes)
{
DoIterateNode(node, elementVisitor);
}
}
}
private static void DoIterateNode(XmlNode node, Action<XmlNode> elementVisitor)
{
elementVisitor(node);
foreach (XmlNode childNode in node.ChildNodes)
{
DoIterateNode(childNode, elementVisitor);
}
}
then i can update my xml nodes as below
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("~/xmlmail.xml"));
var email = new XmlEmail();
doc.IterateThroughAllNodes(
delegate(XmlNode node)
{
if (node.Name.Equals("requestdate"))
node.InnerText= email.RequestDate.ToLongDateString();
if (node.Name.Equals("vehicle"))
{
XmlNodeList childs = node.ChildNodes;
childs.IterateThrough(delegate(XmlNode vnode)
{
if (vnode.Name.Equals("id"))
vnode.InnerText= email.VehicleId.ToString();
if (vnode.Name.Equals("year"))
vnode.InnerText= email.Year.ToString();
if (vnode.Name.Equals("make"))
vnode.InnerText= email.Make;
if (vnode.Name.Equals("model"))
vnode.InnerText= email.Model;
if (vnode.Name.Equals("vin"))
vnode.InnerText= email.Vin;
if (vnode.Name.Equals("trim"))
vnode.InnerText = email.Trim;
});
}
if (node.Name.Equals("customer"))
{
XmlNodeList childs = node.ChildNodes;
childs.IterateThrough(delegate(XmlNode vnode)
{
if (vnode.Attributes != null && (vnode.Name.Equals("name") && vnode.Attributes["part"].Value.Equals("first")))
vnode.InnerText= email.FirstName;
if (vnode.Attributes != null && (vnode.Name.Equals("name") && vnode.Attributes["part"].Value.Equals("last")))
vnode.InnerText= email.LastName;
if (vnode.Name.Equals("email"))
vnode.InnerText= email.Email;
if (vnode.Name.Equals("phone"))
vnode.InnerText= email.Phone;
if (vnode.Name.Equals("comments"))
vnode.InnerText= email.Comments;
if (vnode.Name.Equals("address"))
{
XmlNodeList addresschilds = vnode.ChildNodes;
addresschilds.IterateThrough(delegate(XmlNode anode)
{
if (anode.Name.Equals("street"))
anode.InnerText= email.Street;
if (anode.Name.Equals("city"))
anode.InnerText= email.City;
if (anode.Name.Equals("phone"))
anode.InnerText= email.Phone;
if (anode.Name.Equals("regioncode"))
anode.InnerText= email.RegionCode;
if (anode.Name.Equals("postalcode"))
anode.InnerText= email.Postalode;
if (anode.Name.Equals("country"))
anode.InnerText= email.Country;
});
}
});
}
});

c# to read xml file and update the checkboxes with the nodes

I have an xml file like this:
<servers>
<general name="1">
<service name="ser1"/>
<service name="ser2"/>
</general>
<general name="2">
<service name="ser1"/>
<service name="ser2"/>
</general>
</servers>
In my winform application, I have a treeview list with checkbox property set to true.What I am trying to achieve is that I am attempting to read this xml file and update both the parent and child node to this tree view.
What I have tried is:
XDocument doc = XDocument.Load(#"D:\\path.xml");
TreeNode node;
var gnrl = from general in doc.Descendants("general")
select new
{
parent = general.Attribute("name").Value,
child = general.Descendants("service")
};
//Loop through results
foreach (var general in gnrl)
{
// Add a root node.
node = dcselectview.Nodes.Add(String.Format(general.parent));
foreach (var ser in general.child)
{
// Add a node as a child of the previously added node.
node = node.Nodes.Add(String.Format(ser.Attribute("name").Value));
}
}
it reads the file and all details are updated but not in a proper way. rather it is shown as below:
Needed:
I want the parent element to be on top and down-right to it,the child elements. If possible, it would be nice if I dont have checkboxes for parent elements.
Any help would be really appreciated..
EDIT:
My code edited. Now I am getting as shown in new picture below:
I want the 2 black lines to be in same line,not as child node of another..
Do you want a hierarchical structure, like this?
If so, I recommend you to look at the Treeview:
http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.checkboxes.aspx
Try this you will get
XDocument doc = XDocument.Load(#"D:\\test.xml");
IEnumerable<XElement> Xele = doc.XPathSelectElements("//general");
foreach (XElement xe in Xele.Descendants())
{
//MessageBox.Show(xe.Attribute("name").Value);
dcselectview.Parent.Text =xe.Parent.Attribute("name").Value; // here parent value ----> name="1" and name="2"
dcselectview.Nodes.Add(xe.Attribute("name").Value); // ser1 ser2 ser1 ser2
}
Try this:
public static class TreeViewExtension
{
public static bool LoadNodesFromXML(this TreeView tv, string xml)
{
try
{
XDocument doc = XDocument.Parse(xml);
TreeNode rootNode = new TreeNode();
rootNode.Text = doc.Root.ToString().Split('>')[0] + ">";
rootNode.LoadTreeNodes(doc.Root.Elements());
tv.Nodes.Add(rootNode);
return true;
}
catch { return false; }
}
public static void LoadTreeNodes(this TreeNode parentNode, IEnumerable<XElement> elements)
{
foreach (var e in elements) {
TreeNode childNode = new TreeNode();
childNode.Text = e.ToString().Split('>')[0] + ">";
parentNode.Nodes.Add(childNode);
childNode.LoadTreeNodes(e.Elements());
}
}
}
//Usage:
var yourInputXMLString = "<servers><general name=\"1\"><service name=\"ser1\"/>" +
"<service name=\"ser2\"/></general><general name=\"2\">" +
"<service name=\"ser1\"/><service name=\"ser2\"/>" +
"</general></servers>";
treeView1.LoadNodesFromXML(yourInputXMLString);
You have to add parent as a node first
public static bool LoadNodesFromXML()
{
XDocument doc = XDocument.Load(#"D:\\path.xml");
var root = doc.Root;
var childenode = dcselectview.Nodes.Add(root.Attribute("Name").Value);
foreach (var xElement in root .Elements())
{
InsertNode(childenode, xElement);
}
}
private void InsertNode(TreeNode parent, XElement element)
{
var childenode = parent.Nodes.Add(element.Attribute("Name").Value);
if(element.Elements().Count() > 0)
foreach (var xElement in element.Elements())
{
InsertNode(childenode, xElement);
}
}
Thanks all for your help::But I have found another solution of my own::
XDocument doc = XDocument.Load(#"path\\test.xml");
// Add nodes to treeView1.
TreeNode pnode;
TreeNode cnode;
var gnrl = from general in doc.Descendants("general")
select new
{
parent = general.Attribute("name").Value,
child = general.Descendants("service")
};
//Loop through results
foreach (var general in gnrl)
{
// Add a root node.
pnode = treeview.Nodes.Add(String.Format(general.parent));
foreach (var ser in general.child)
{
// Add a node as a child of the previously added node.
cnode = pnode.Nodes.Add(String.Format(ser.Attribute("name").Value));
}
}

using xmldocument to read xml

<?xml version="1.0" encoding="utf-8" ?>
<testcase>
<date>4/12/13</date>
<name>Mrinal</name>
<subject>xmlTest</subject>
</testcase>
I am trying to read the above xml using c#, But i get null exception in the try catch block can any body suggest the required change.
static void Main(string[] args)
{
XmlDocument xd = new XmlDocument();
xd.Load("C:/Users/mkumar/Documents/testcase.xml");
XmlNodeList nodelist = xd.SelectNodes("/testcase"); // get all <testcase> nodes
foreach (XmlNode node in nodelist) // for each <testcase> node
{
CommonLib.TestCase tc = new CommonLib.TestCase();
try
{
tc.name = node.Attributes.GetNamedItem("date").Value;
tc.date = node.Attributes.GetNamedItem("name").Value;
tc.sub = node.Attributes.GetNamedItem("subject").Value;
}
catch (Exception e)
{
MessageBox.Show("Error in reading XML", "xmlError", MessageBoxButtons.OK);
}
........
.....
The testcase element has no attributes. You should be looking to it's child nodes:
tc.name = node.SelectSingleNode("name").InnerText;
tc.date = node.SelectSingleNode("date").InnerText;
tc.sub = node.SelectSingleNode("subject").InnerText;
You might process all nodes like this:
var testCases = nodelist
.Cast<XmlNode>()
.Select(x => new CommonLib.TestCase()
{
name = x.SelectSingleNode("name").InnerText,
date = x.SelectSingleNode("date").InnerText,
sub = x.SelectSingleNode("subject").InnerText
})
.ToList();
You can use LINQ to XML to select all testcase elements from your xml and parse them to TestCase instances:
var xdoc = XDocument.Load("C:/Users/mkumar/Documents/testcase.xml");
var testCases = from tc in xdoc.Descendants("testcase")
select new CommonLib.TestCase {
date = (string)tc.Element("date"),
name = (string)tc.Element("name"),
sub= (string)tc.Element("subject")
};
BTW you have only one testcase element currently, which is root of XML file. So, you can do instead:
var tc = XElement.Load("C:/Users/mkumar/Documents/testcase.xml");
var testCase = new CommonLib.TestCase {
date = (string)tc.Element("date"),
name = (string)tc.Element("name"),
sub= (string)tc.Element("subject")
};
private static void Main(string[] args)
{
XmlDocument xd = new XmlDocument();
xd.Load("C:\\test1.xml");
XmlNodeList nodelist = xd.SelectNodes("/testcase"); // get all <testcase> nodes
foreach (XmlNode node in nodelist) // for each <testcase> node
{
try
{
var name = node.SelectSingleNode("date").InnerText;
var date = node.Attributes.GetNamedItem("name").Value;
var sub = node.Attributes.GetNamedItem("subject").Value;
}
catch (Exception e)
{
MessageBox.Show("Error in reading XML", "xmlError", MessageBoxButtons.OK);
}
}
This will work I have test it #Alex correct answer
You are trying to read attributes whereas date, name and subject are not attributes. They are subnodes.
your code should be like this
XmlDocument xd = new XmlDocument();
xd.Load("test.xml");
XmlNodeList nodelist = xd.SelectNodes("/testcase"); // get all <testcase> nodes
foreach (XmlNode node in nodelist) // for each <testcase> node
{
try
{
string name = node.SelectSingleNode("name").InnerText;
string date = node.SelectSingleNode("date").InnerText;
string sub = node.SelectSingleNode("subject").InnerText;
}
catch (Exception ex)
{
MessageBox.Show("Error in reading XML", "xmlError", MessageBoxButtons.OK);
}
}
Your Xml do not contain Attributes. date, name and subject - it's Child Nodes of the testcase Node.
Try this:
...
tc.name = node["name"].InnerText;
...
or this:
...
tc.name = node.SelectSingleNode("name").InnerText;
...

Foreach loop XmlNodeList

Currently I have the following code:
XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");
XmlNodeList tweets = xDoc.GetElementsByTagName("text");
foreach (int i in tweets)
{
if (tweets[i].InnerText.Length > 0)
{
MessageBox.Show(tweets[i].InnerText);
}
}
Which doesn't work, it gives me System.InvalidCastException on the foreach line.
The following code works perfectly (no foreach, the i is replaced with a zero):
XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");
XmlNodeList tweets = xDoc.GetElementsByTagName("text");
if (tweets[0].InnerText.Length > 0)
{
MessageBox.Show(tweets[0].InnerText);
}
I know that there is already a marked answer, but you can do it like you did in your first try, you just need to replace the int with XmlNode
XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");
XmlNodeList tweets = xDoc.GetElementsByTagName("text");
foreach (XmlNode i in tweets)
{
if (i.InnerText.Length > 0)
{
MessageBox.Show(i.InnerText);
}
}
tweets is a node list. I think that what you're trying to do is this:
XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");
XmlNodeList tweets = xDoc.GetElementsByTagName("text");
for (int i = 0; i < tweets.Count; i++)
{
if (tweets[i].InnerText.Length > 0)
{
MessageBox.Show(tweets[i].InnerText);
}
}
It is not of Int type, That is the reason you are getting a casting exception. You can either replace int with the appropriate type or simply make use of type inference (implicitly typed variables) to handle this. Here i am using typeinference.by saying type as var, The compiler will understand it is of type of the iterator variable in tweets collection
foreach (var i in tweets)
{
if (i!=null)
{
string tweet= (((System.Xml.XmlElement)(i))).InnerText;
MessageBox.Show(tweet);
}
}
EDIT : With the Wonderful LINQtoXML, Your code can be rewritten like this.
string url = "http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter";
XElement elm = XElement.Load(url);
if (elm != null)
{
foreach (var status in elm.Elements("status"))
{
string tweet = status.Element("text").Value;
MessageBox.Show(ss);
}
}
All the answers seem to be a bit outdated Imperative examples so I will add a declarative one. This is not doing what the OP wanted but I'm sure you'll get the point.
public static List<System.Xml.XmlNode> toList(System.Xml.XmlNodeList nodelist){
List<System.Xml.XmlNode> nodes = new List<System.Xml.XmlNode>();
foreach (System.Xml.XmlNode node in nodelist)
{
nodes.Add(node);
}
return nodes;
}
public static ReadMeObject setXml(ReadMeObject readmeObject){
readmeObject.xmlDocument = new System.Xml.XmlDocument();
readmeObject.xmlDocument.LoadXml("<body>"+readmeObject.htmlStringContent+"</body>");
System.Xml.XmlNodeList images = readmeObject.xmlDocument.SelectNodes("//img");
Array.ForEach(
Functions.toList( images )
.Where((image) => image.Attributes != null)
.Where((image) => image.Attributes["src"] != null)
.Where((image) => image.Attributes["src"].Value != "")
.ToArray()
, (image) => {
Console.WriteLine(image.Attributes["src"].Value);
}
);
return readmeObject;
}
foreach (XmlNode node in tweets)
{
if (tweets[i].InnerText.Length > 0)
{
MessageBox.Show(tweets[node].InnerText);
}
}
I've changed the 'I', which you cannot use, to XmlNode, which selects a single line of your list.
You can loop through the Collection with .GetEnumerator()
this code is taken Microsoft Documentation :
XmlNodeList elemList = root.GetElementsByTagName("title");
IEnumerator ienum = elemList.GetEnumerator();
while (ienum.MoveNext()) {
XmlNode title = (XmlNode) ienum.Current;
Console.WriteLine(title.InnerText);
}
Use this simple extension method to iterate through XmlNodeList:
public static void ForEachXml<TXmlNode>(this XmlNodeList nodeList, Action<TXmlNode> action)
{
foreach (TXmlNode node in nodeList) action(node);
}
Method Call:
xDoc.GetElementsByTagName("text").ForEachXML<XmlNode>(tweet =>
{
if (tweet.InnerText.Length > 0)
MessageBox.Show(tweet.InnerText);
});

Categories