How to get value of some object in XML string in C#? - c#

I have this XML String :
<RESPONSE>
<SINGLE>
<KEY name="sitename">
<VALUE>Stackoverflow</VALUE>
</KEY>
<KEY name="username">
<VALUE>this value</VALUE>
</KEY>
</SINGLE>
</RESPONSE>
How to get value from Key that name "username" ? I want to get value of "this value" in my code. I try deserialized and any other code but it doesnt work. Please help me, thanks :D
Edit:
I tried using this code :
XDocument doc = XDocument.Load( "myXML.xml" );
var keys = doc.Descendants( "KEY" );
foreach ( var VALUE in keys )
{
Console.WriteLine( VALUE.Value );
}
But how did I get the Value only from KEY that named "Username" ? Thanks :))

You can probably use an xpath to do this. The following is an example XPath that will provide a node with name matching "sitename":
//KEY[#name="sitename"]
You can modify this slightly to find all nodes with a "name" attribute or to just find specific names. For more examples of how to use XPath see the MSDN site for XPath. The following is a snippet of C# code that shows you how to use this XPath (again, you can generalize for whatever XPath you need):
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
// load
XmlDocument doc = new XmlDocument();
doc.LoadXml(example_xml);
// Query single or multiple nodes using the XPath, do what you want with this node!
var desiredNode = doc.SelectSingleNode("//KEY[#name=\"sitename\"]");
Best of luck!

For completeness here is a System.Xml.Linq version, with the foreachs and where's being System.Linq for good measure. This basically the questioner's attempt, with a where to filter according to attribute.
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
XDocument doc = XDocument.Parse(example_xml);
var keys = doc.Descendants("KEY");
var userKeys = keys.Where(item => item.Attribute("name").Value == "username").ToList();
userKeys.ForEach(item => Console.WriteLine(item.Value));

Lets consider your xml document as XYZ.xml, then you may try below code if you are using C#, below is the example only
XmlDocument Doc = new XmlDocument();
Doc.Load(Server.MapPath(".../xyz.xml"));
XmlNodeList itemList = Doc.DocumentElement.SelectNodes("KEY");
foreach (XmlNode currNode in itemList)
{
string name = string.Empty;
XmlNode item = currNode.SelectSingleNode("KEY");
if(currNode["name"].InnerText == "username")//if you are aware of key name, use this condition
{
name = item.Attributes["name"].Value.ToString(); // or currNode["name"].InnerText;
}
}

Related

Xml Path how to read property name

i need some help. i've got xml like this:
<?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
</session-factory>
</hibernate-configuration>
and i want to read property NAME and value (value is between
i have done something like this
XPathNodeIterator iterator = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property/#name", manager);
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator.MoveNext() && iterator2.MoveNext())
{
var name = iterator.Current.Value;
var property = iterator2.Current.Value;
}
but it is possible to have only one iterator in that case which i could use to get name and property ?
You can use only the 2nd iterator and use GetAttribute() to read name attribute value :
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator2.MoveNext())
{
var navigator = iterator.Current;
var name = navigator.GetAttribute("name","");
var property = navigator.Value;
}
Anyway, the entire task can be much simpler using XmlDocument, or using LINQ-to-XML as demonstrated below :
var doc = XDocument.Load("path_to_your_xml.xml");
XNamespace d = "urn:nhibernate-configuration-2.2";
foreach(var prop in doc.Descendants(d+"property")
{
var name = (string)prop.Attribute("name");
var property = (string)prop;
}

Getting an XElement with a namespace via XPathSelectElements

I have an XML e.g.
<?xml version="1.0" encoding="utf-8"?>
<A1>
<B2>
<C3 id="1">
<D7>
<E5 id="abc" />
</D7>
<D4 id="1">
<E5 id="abc" />
</D4>
<D4 id="2">
<E5 id="abc" />
</D4>
</C3>
</B2>
</A1>
This is may sample code:
var xDoc = XDocument.Load("Test.xml");
string xPath = "//B2/C3/D4";
//or string xPath = "//B2/C3/D4[#id='1']";
var eleList = xDoc.XPathSelectElements(xPath).ToList();
foreach (var xElement in eleList)
{
Console.WriteLine(xElement);
}
It works perfectly, but if I add a namespace to the root node A1, this code doesn't work.
Upon searching for solutions, I found this one, but it uses the Descendants() method to query the XML. From my understanding, this solution would fail if I was searching for <E5> because the same tag exists for <D7>, <D4 id="1"> and <D4 id="2">
My requirement is to search if a node exists at a particular XPath. If there is a way of doing this using Descendants, I'd be delighted to use it. If not, please guide me on how to search using the name space.
My apologies in case this is a duplicate.
To keep using XPath, you can use something link this:
var xDoc = XDocument.Parse(#"<?xml version='1.0' encoding='utf-8'?>
<A1 xmlns='urn:sample'>
<B2>
<C3 id='1'>
<D7><E5 id='abc' /></D7>
<D4 id='1'><E5 id='abc' /></D4>
<D4 id='2'><E5 id='abc' /></D4>
</C3>
</B2>
</A1>");
// Notice this
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("sample", "urn:sample");
string xPath = "//sample:B2/sample:C3/sample:D4";
var eleList = xDoc.XPathSelectElements(xPath, nsmgr).ToList();
foreach (var xElement in eleList)
{
Console.WriteLine(xElement);
}
but it uses the Descendants() method to query the XML. From my understanding, this solution would fail if I was searching for because the same tag exists for , and
I'm pretty sure you're not quite understanding how that works. From the MSDN documentation:
Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection.
So in your case, just do this:
xDoc.RootNode
.Descendants("E5")
.Where(n => n.Parent.Name.LocalName == "B4");
Try this
var xDoc = XDocument.Parse("<A1><B2><C3 id=\"1\"><D7><E5 id=\"abc\" /></D7><D4 id=\"1\"><E5 id=\"abc\" /></D4><D4 id=\"2\"><E5 id=\"abc\" /></D4></C3></B2></A1>");
foreach (XElement item in xDoc.Element("A1").Elements("B2").Elements("C3").Elements("D4"))
{
Console.WriteLine(item.Element("E5").Value);//to get the value of E5
Console.WriteLine(item.Element("E5").Attribute("id").Value);//to get the value of attribute
}

Namespaced nodes of the same name - content of the attributes needed

got this document:
<uniprot xmlns="http://uniprot.org/uniprot" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance" xsi:schemaLocation="http://uniprot.org/uniprot http://www.uniprot.org/support/docs/uniprot.xsd">
<entry dataset="Swiss-Prot" created="1986-07-21" modified="2013-10-16" version="88">
<dbReference type="GO" id="GO:0006412">
<property type="term" value="P:translation"/>
<property type="evidence" value="IEA:InterPro"/>
</dbReference>
<dbReference type="HAMAP" id="MF_00294">
<property type="entry name" value="Ribosomal_L33"/>
<property type="match status" value="1"/>
</dbReference>
<dbReference type="InterPro" id="IPR001705">
<property type="entry name" value="Ribosomal_L33"/>
</dbReference>
Right now, I'm using this to grab the inner text of nodes, which works fine...BUT...
XmlDocument XMLdoc = new XmlDocument();
XMLdoc.Load(Datapath);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(XMLdoc.NameTable);
nsmgr.AddNamespace("ns", "http://uniprot.org/uniprot");
String NodeName = XMLdoc.SelectSingleNode("//ns:fullName", nsmgr).InnerText;
... I need to grab the attributes of and whether type's content is GO or not and if so, get the following data of that exact node, namely id and value. Been thinking about and googling for this for several hours and I just lack the knowledge to get anywhere.
I'd suggest using Linq to Xml, I find it a lot easier than XmlDocument and XPath queries, but that is at least partially personal preference.
I'm not quite sure what you mean by the "value" of each element with a type of "GO", but this should get you most of the way there. goTypeNodes will contain a collection of those nodes that have a type of "GO" with their ID and type values, and additionally contains the property elements underneath them, so if by "value" you mean the value of the property elements underneath them, it is trivial to get at that from there.
XNamespace ns = "http://uniprot.org/uniprot";
XDocument doc = XDocument.Load(#"C:\SO\Foo.xml");
var goTypeNodes = from n in doc.Descendants(ns + "dbReference")
select new { Id = n.Attribute("id").Value, Type = n.Attribute("type").Value, Properties = n.Elements()};
By the way, your sample XML is missing closing tags for uniprot and entry.
Actually I managed to solve the problem:
XmlNodeList Testi = XMLdoc.SelectNodes("//ns:dbReference", nsmgr);
foreach (XmlNode xn in Testi)
{
if (xn.Attributes["type"].Value == "GO")
{
String Testilator = xn.Attributes["id"].Value;
String Testilator2 = xn.FirstChild.Attributes["value"].Value;
}
}

Retrieving a Deeply Nested Value in an XML File

I'm trying to read a property in an XML file using C# and LINQ XML and I can't retrieve a value that is deeply nested in the tree. The value I'm trying to get is the contents of <Value> near <DisplayName>Add Your Comments</DisplayName>. Every <OrderProduct id=???> may have its own comments.
I can read other properties in the XML file using LINQ, but I'm confused how to go about reading something so deeply nested.
Thanks.
<?xml version="1.0" encoding="utf-16"?>
<OrderXml>
<Order>
<OrderProducts>
<OrderProduct id="1">
.
.
.
</OrderProduct>
<OrderProduct id="2">
<PropertyValues>
<PropertyValue>
<Property id="10786">
<DisplayName>Base</DisplayName>
</Property>
<Value />
</PropertyValue>
<PropertyValue>
<Property id="10846">
<DisplayName>Add Your Comments</DisplayName>
</Property>
<Value>this is a comment</Value>
</PropertyValue>
</PropertyValues>
</OrderProduct>
</OrderProducts>
</Order>
</OrderXml>
This is the code I have so far. I can retrieve the "Add Your Comments" part, but I'm stuck in how to get the part that follows it.
string productOrderID = "";
string productName = "";
XElement xelement;
xelement = XElement.Load (#"D:\Order.xml");
IEnumerable<XElement> Products = xelement.Descendants ("OrderProduct");
foreach (var order in Products)
{
productOrderID = order.Attribute ("id").Value;
productName = order.Element ("Product").Element ("Name").Value;
Console.WriteLine ("productOrderID: {0}", productOrderID);
Console.WriteLine ("productName: {0}", productName);
Console.WriteLine ("");
IEnumerable<XElement> PropertyValues = xelement.Descendants ("PropertyValues").Elements ("PropertyValue");
foreach (var propValue in PropertyValues.Elements ("Property").Elements ("DisplayName"))
{
Console.WriteLine ("Property ID: {0}", propValue.Value);
if (propValue.Value == "Add Your Comments")
{
Console.WriteLine ("---");
}
}
}
You can use Descendants to search for nodes in document no matter where they are:
string name = "Add Your Comments";
var value = xdoc
.Descendants("PropertyValue")
.Where(pv => (string)pv.Element("Property").Element("DisplayName") == name)
.Select(pv => (string)pv.Element("Value"))
.FirstOrDefault();
Output:
this is a comment

Reading an XML file into a TreeView

I am trying to load an XML file onto my GUI using a TreeView control.
However, I am using a proprietary layout for my XML file.
The XML is structured like this:
<ConfiguratorConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Section>
<Class ID="Example" Name="CompanyName.Example" Assembly="Example.dll">
<Interface>
<Property Name="exampleProperty1" Value="exampleValue" />
<Property Name="exampleProperty2" Value="exampleValue" />
<Property Name="exampleProperty3" Value="exampleValue" />
</Interface>
</Class>
</Section>
</ConfiguratorConfig>
I'd like the output to be structured like:
Class "Example"
Property "exampleProperty1"
Property "exampleProperty2"
Property "exampleProperty3"
I'm totally new to using XML. 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 2005.
Thanks for the help!
You can iterate through nodes using XmlDocument, you can put this demo in a Main method of a console application:
string xml = #"<ConfiguratorConfig xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<Section>
<Class ID=""Example"" Name=""CompanyName.Example"" Assembly=""Example.dll"">
<Interface>
<Property Name=""exampleProperty1"" Value=""exampleValue"" />
<Property Name=""exampleProperty2"" Value=""exampleValue"" />
<Property Name=""exampleProperty3"" Value=""exampleValue"" />
</Interface>
</Class>
</Section></ConfiguratorConfig>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach (XmlNode _class in doc.SelectNodes(#"/ConfiguratorConfig/Section/Class"))
{
string name = _class.Attributes["ID"].Value;
Console.WriteLine(name);
foreach (XmlElement element in _class.SelectNodes(#"Interface/Property"))
{
if (element.HasAttribute("Name"))
{
string nameAttributeValue = element.Attributes["Name"].Value;
Console.WriteLine(nameAttributeValue);
}
}
}
If you're using version of .NET higher than 3.0 you can use XDocument class (recommended if you can choose).
XDocument xdoc = XDocument.Parse(xml);
foreach (XElement _class in xdoc.Descendants("Class"))
{
string name = _class.Attribute("ID").Value;
Console.WriteLine(name);
foreach (XElement element in _class.Descendants("Property"))
{
XAttribute attributeValue = element.Attribute("Name");
if (attributeValue != null)
{
string nameAttributeValue = attributeValue.Value;
Console.WriteLine(nameAttributeValue);
}
}
}

Categories