Get content of XML node using c# - c#

simple question but I've been dinking around with it for an hour and it's really starting to frustrate me. I have XML that looks like this:
<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>
And all I want to do is use C# to get the string stored between <Ambassador> and </Ambassador>.
So far I have:
XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
which selects the note just fine, now how in the world do I get the content in there?

May I suggest having a look at LINQ-to-XML (System.Xml.Linq)?
var doc = XDocument.Load("C:\\test.xml");
string result = (string)doc.Root.Element("Ambassador");
LINQ-to-XML is much more friendly than the Xml* classes (System.Xml).
Otherwise you should be able to get the value of the element by retrieving the InnerText property.
string result = x.InnerText;

The InnerText property should work fine for you.
http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.innertext.aspx
FWIW, you might consider switching API to linq-to-xml (XElement and friends) as IMHO it's a friendly, easier API to interact with.
System.Xml version (NOTE: no casting to XmlElement needed)
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var node = doc.SelectSingleNode("/TimelineInfo/Ambassador");
Console.WriteLine(node.InnerText);
linq-to-xml version:
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
var root = XElement.Parse(xml);
string ambassador = (string)root.Element("Ambassador");
Console.WriteLine(ambassador);

XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
x.InnerText will return the contents

Try using Linq to XML - it provides a very easy way to query xml datasources - http://msdn.microsoft.com/en-us/library/bb387098%28v=VS.100%29.aspx

Related

How to Parse Nested XML Nodes in C#

I am very new to C#, but it seems as though this should be pretty straight forward. I am trying to parse an XML string returned from a web feed that looks like this:
<autnresponse xmlns:autn="http://schemas.autonomy.com/aci/">
<action>QUERY</action>
<response>SUCCESS</response>
<responsedata>
<autn:numhits>6</autn:numhits>
<autn:hit>
<autn:reference>http://something.what.com/index.php?title=DPM</autn:reference>
<autn:id>548166</autn:id>
<autn:section>0</autn:section>
<autn:weight>87.44</autn:weight>
<autn:links>Castlmania,POUCH</autn:links>
<autn:database>Postgres</autn:database>
<autn:title>A Pouch and Mail - Castlmania</autn:title>
<autn:content>
<DOCUMENT>
<DRETITLE>Castlmania Pouch and Mail - Castlmania</DRETITLE>
<DRECONTENT>A paragraph of sorts that would contain content</DRECONTENT>
</DOCUMENT>
</autn:content>
</autn:hit>
<autn:hit>...</autn:hit>
<autn:hit>...</autn:hit>
<autn:hit>...</autn:hit>
<autn:hit>...</autn:hit>
</autnresponse>
with no luck.
I am using this code to start:
XmlDocument xmlString = new XmlDocument();
xmlString.LoadXml(xmlUrl);
XmlElement root = xmlString.DocumentElement;
XmlNode GeneralInformationNode =
root.SelectSingleNode("//autnresponse/responsedata/autn:hit");
foreach (XmlNode node in GeneralInformationNode)
{
Console.Write("reference: "+node["autn:reference"]+" Title:"+node["DRETITLE"]+"<br />);
}
And I would like to print the DRETITLE and autn:reference element of within each of the autn:hit elements. Is that even doable with my approach?
I have tried looking and several example on the good old web like this to no avail.
The error that comes back is:
System.Xml.XPath.XpathEception {NameSpace Manager or XsltContext
needed. ...}
Thanks in advance.
UPDATE:
In trying to use XmlNamespaceManager, one has to give it a url to the schema definition like so:
XmlNamespaceManager namespmng = new XmlNamespaceManager (xmlString.NameTable);
namespmng.AddNamespace("autn","http://someURL.com/XMLschema");
The problem seems to be that now the error is gone, but the data is not displaying. I should mention that I am working off of a machine that does not have internet connectivity. The other thing is the schema seems to be unavailable. I am guessing that XmlNamespaceManager would work once able to connect to the internet right?
Using System.Xml.Linq it could be something like this:
var doc = XElement.Load(xmlUrl);
var ns = doc.GetNamespaceOfPrefix("autn");
foreach (var hit in doc.Descendants(ns + "hit"))
{
var reference = hit.Element(ns + "reference").Value;
var dretitle = hit.Descendants("DRETITLE").Single().Value;
WriteLine($"ref: {reference} title: {dretitle}");
}
Firstly, the exception you're getting is because you haven't loaded the namespace using the XmlNamespaceManager for the xml you're parsing. Something like this:
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlString.NameTable);
if (root.Attributes["xmlns:autn"] != null)
{
uri = root.Attributes["xmlns:autn"].Value;
namespaceManager.AddNamespace("autn", uri);
}
Secondly, what you're trying to do is possible. I'd suggest using root.SelectNodes(<your xpath here>) which will return a collection of autn:hit nodes that you can loop through instead of SelectSingleNode which will return one node. Within that you can drill down to the content/DOCUMENT/DRETITLE and pull the text for the DRETITLE node using either XmlNode.Value if you select the text specifically or XmlNode.InnerText on the DRETITLE node.

Parsing xml response - Select specific node based on value of another node

I'm new to xml so I'm not sure if I worded the question correctly, but I will do my best to explain.
Basically, I'm trying to parse an xml response in C# such as the one below:
<Premium>
<TotalPremiumAmount>87</TotalPremiumAmount>
<StandardPremium>87</StandardPremium>
<OptionalPremium>0</OptionalPremium>
<StandardTax>0</StandardTax>
<OptionalTax>0</OptionalTax>
<ExtendedTax>0</ExtendedTax>
<ExtendedPremium>0</ExtendedPremium>
<PromotionalPremium>0</PromotionalPremium>
<FeesPremium>0</FeesPremium>
<FeesTax>0</FeesTax>
<StandardFeesPremium>0</StandardFeesPremium>
<OptionalFeesPremium>0</OptionalFeesPremium>
<Tax>0</Tax>
<StandardPremiumDistribution>
<Travelers>
<Traveler>
<TravelerPremium>42</TravelerPremium>
<TravelerTax>0</TravelerTax>
</Traveler>
<Traveler>
<TravelerPremium>45</TravelerPremium>
<TravelerTax>0</TravelerTax>
</Traveler>
</Travelers>
</StandardPremiumDistribution>
<PackagePremiumDistribution>
<Packages>
<Package>
<PackageID>20265</PackageID>
<PackageName />
<PackageTypeID>12</PackageTypeID>
<Premium>87</Premium>
<Fees>0</Fees>
<Tax>0</Tax>
<Travelers>
<Traveler>
<TravelerID>0</TravelerID>
<Premium>42</Premium>
<Tax>0</Tax>
</Traveler>
<Traveler>
<TravelerID>1</TravelerID>
<Premium>45</Premium>
<Tax>0</Tax>
</Traveler>
</Travelers>
</Package>
</Packages>
</PackagePremiumDistribution>
</Premium>
I would like to get the value of the (Traveler) Premium. In the case of only one traveler, I have been using an XMLDocument and the 'SelectSingleNode" function. For example I could do something like:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResponse);
var premium = xmlDoc.SelectSingleNode("//TravelerPremium").InnerText;
But this wouldn't work when multiple travelers are returned under one plan. For example, I need the premium when TravelerID = 0. How would I go about doing this?
Thanks.
Using XmlDocument:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResponse);
var premium = xmlDoc.SelectSingleNode("//Premium[../TravelerID = '0']")
You could also iterate through the nodes if multiple could match on this condition like so:
foreach(var premium in xmldoc.SelectNodes("//Premium[../TravelerID = '0']")
{
// do work on each premium node where TravelerID = 0
}
I'd encourage you to look into using LINQ to XML - it's generally easier to work with and will be more performant in most cases. You could even still use XPath expressions, but the following would work:
XDocument xdoc = XDocument.Load(xmlResponse);
var premium = (string)xdoc.Descendants("Traveler").Where(x => (string)x.Element("TravelerID") == "0").Element("Premium");
Assuming your xml looks like that, try something like this:
XmlDocument doc = new XmlDocument();
xmlDoc.Load(xmlResponse);
if (doc.HasChildNodes)
{
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
if (node.Name == "StandardPremiumDistribution")
{
XmlNodeList xnList = node.SelectNodes("//Travelers");
double travelerPremium= xnList.Item(z).FirstChild.InnerText);
}}
Based on this, I think you're gonna do it.
Let's suppose you have a file called XMLFile1.xml with the XML you posted you can iterate through all your TravelerPremium with the following code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("XMLFile1.xml");
XmlNodeList premiums = xmlDoc.SelectNodes("//TravelerPremium");
foreach(XmlNode node in premiums)
{
MessageBox.Show(node.FirstChild.InnerText);
}
You can also acces the other elements with similar code.

XmlElement convert open tag to string c#

I need to convert to string a subset of OuterXml content of a XmlElement as in the following example.
Imagine I have an XmlElement object representing the some-element tag
<some-element attribute="value">
<inner-element>
text content
</inner-element>
</some-element>
What's the best approach to get a string that is just <some-element attribute="value">?
If possible, I'd prefer a solution without regular expressions involved, but using DOM classes
You can get the full XML of the element(which includes the close tag) by shallow cloning the node and then grabbing the outer XML of the node:
var xml = #"<some-element attribute=""value"">
<inner-element>
text content
</inner-element>
</some-element>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
MessageBox.Show(doc.DocumentElement.CloneNode(false).OuterXml);
I think after that point you will have to do some string manipulation to get exactly what you want, but that is relatively easy:
var outer = doc.DocumentElement.CloneNode(false).OuterXml;
var final = outer.Substring(0, outer.LastIndexOf(">", outer.Length - 2)+1);
MessageBox.Show(final);
I finally solved it by creating a temporary XElement instead using LINQ
IEnumerable<XAttribute> attributes = (from XmlAttribute xmlAttribute in node.Attributes select new XAttribute(xmlAttribute.Name, xmlAttribute.Value));
var xElement = new XElement(node.Name, attributes);
return xElement.ToString();

Get xml node using c#

I have a request that returns a large xml file. I have the file in a XmlDocument type in my application. From that Doc how can I read an element like this:
<gphoto:videostatus>final</gphoto:videostatus>
I would like to pull that value final from that element. Also If i have multiple elements as well, can I pull that into a list? thanks for any advice.
If you already have an XmlDocument then you can use the function GetElementsByTagName() to create an XmlNodeList that can be accessed similar to an array.
http://msdn.microsoft.com/en-us/library/dc0c9ekk.aspx
//Create the XmlDocument.
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");
//Display all the book titles.
XmlNodeList elemList = doc.GetElementsByTagName("title");
for (int i=0; i < elemList.Count; i++)
{
Console.WriteLine(elemList[i].InnerXml);
}
You can select nodes using XPath and SelectSingleNode SelectNodes. Look at http://www.codeproject.com/Articles/9494/Manipulate-XML-data-with-XPath-and-XmlDocument-C for examples. Then you can use for example InnerText to get final. Maybe you need to work with namespaces (gphoto). The //videostatus would select all videostatus elements
You can try using LINQ
XNamespace ns = XNamespace.Get(""); //use the xmnls namespace here
XElement element = XElement.Load(""); // xml file path
var result = element.Descendants(ns + "videostatus")
.Select(o =>o.Value).ToList();
foreach(var values in value)
{
}
Thanks
Deepu

How to get the value from XML?

I'm making a small tool for checking the material number from the XML file.
I know this quite easy for you experts and I would like to ask for your help on this to get me started on this. On my machine I have .NET 2.0 framework I guess, and VS C# Express 2005 installed.
I have an XML that contains data of a material. It is located at my local drive. I am able now to browse the XML file and save the file in a string variable. Well, that's what I have done so far..
if(folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "Product.xml");
string prodFile = files[0];
...
...
Suppose this is the structure of the XML:
<Record>
<Product>
<Material_Number>20209485</Material_Number>
<Product_Type>Type1</Product_Type>
...
...
</Product>
</Record>
How can I get the material number value?
You can use the XmlDocument class for loading your XML File into a DOM.
MSDN - This class implements the W3C Document Object Model (DOM) Level 1 Core and the Core DOM Level 2. The DOM is an in-memory (cache) tree representation of an XML document and enables the navigation and editing of this document. Because XmlDocument implements the IXPathNavigable interface it can also be used as the source document for the XslTransform class.
Sample
There are many ways to read your value. I really encourage you to read Working with Xml DOM
XmlNodeList list = xml.GetElementsByTagName("Product");
XmlAttributeCollection attr = list[0].Attributes;
string materialNumber = list[0].ChildNodes[0].InnerText;
or
XmlNodeList list = xml.GetElementsByTagName("Material_Number");
string materialNumber = list[0].InnerText;
More Information
MSDN - XmlDocument Class
Working with Xml DOM
You could also use XPathNavigator and XPathExpression with XmlDocument.
var xmlDoc = new XmlDocument();
xmlDoc.Load("Product.xml") //or xmlDoc.LoadXml(xmlString);
var xmlNav = xmlDoc.CreateNavigator();
string materialNum;
var iterator = xmlNav.Select("/Record/Product/Material_Number");
if (iterator.MoveNext() && iterator.Current != null)
materialNum = iterator.Current.Value;
If you use .Net 3.0+ you could use System.Xml.Linq.XDocument.
var xdoc = XDocument.Load("Product.xml"); //or var xdoc = XDocument.Parse(xmlString);
var materialNum = xdoc.Root.Element("Product").Element("Material_Number").Value;
I was able to find a solution. Not so elegant though...
XmlDocument xmlDoc= new XmlDocument();
xmlDoc.Load(#"C:\Product.xml");
XmlNodeList a = xmlDoc.GetElementsByTagName("Material_Number");
string materialNumber = a[0].InnerText;

Categories