how to get specific nodes which has specific attribute in c# - c#

I want to find the nodes which has a specific attribute (like in example below we have attribute attr )
<root>
<anynode id="1" attr="abc">
first node
</anynode>
<anynode id="2">
2nd node
</anynode>
<anynode id="3" attr="abc">
3rd node
</anynode>
<anynode id="4" attr="def">
4th node
</anynode>
</root>
and i want it to traverse with XMLDocument and XDocument both
and if i can get value of ID and ATTR in one ittration that would be great
i have googled little bit but i didnt find any path which can help me lead to
final result i want
1,abc , first node
3,abc , 3rd node
4,def , 4th node
any help will be appreciated

Using the System.Xml.Linq namespace we can take advantage of the XDocument class to find the "id" and "attr" attributes of the "anynode" element.
var xmlDocument = XDocument.Load(#"path to xml file");
var nodes = xmlDocument.Element("root")?.Elements("anynode");
if (nodes == null)
return;
foreach (var node in nodes)
{
var id = node.Attribute("id")?.Value;
var attr = node.Attribute("attr")?.Value;
Console.WriteLine($"ID = {id}, ATTR = {attr}");
}

Related

Getting a whole XML node with its markups in a string

Given the following XML example
<aaa>
<bbb id="1">
<ccc att="123"/>
<ccc att="456"/>
<ccc att="789"/>
</bbb>
<bbb id="2">
<ccc att="321"/>
<ccc att="654"/>
<ccc att="987"/>
</bbb>
</aaa>
as an XmlDocument object called xDoc1, I managed to remove the first bbb node thanks to its ID and an XPath instruction, leaving the second bbb node alone in the aaa one.
But now I want to get this removed node and its markups in a single string, as the InnerText value of this node is equal to
<ccc att="123"/><ccc att="456"/><ccc att="789"/>
but I want my string to be equal to
<bbb id='1'><ccc att="123"/><ccc att="456"/><ccc att="789"/></bbb>
How can I do so ? Using XmlDocument is mandatory.
I tried to use the ParentNode method, but then it includes the other bbb node.
My C# code for the moment :
xDoc1 = new XmlDocument();
xDoc1.Load("file.xml"); // Containing the given example above.
XmlNodeList nodes = xDoc1.SelectSingleNodes("//bbb[#id='1']");
foreach (XmlNode n in nodes)
{
XmlNode parent = n.ParentNode;
parent.RemoveChild(n);
}
// At this point, xDoc1 does not contain the first bbb node (id='1') anymore.
Use OuterXml property of XmlNode
xDoc1 = new XmlDocument();
xDoc1.Load("file.xml"); // Containing the given example above.
XmlNodeList nodes = xDoc1.SelectSingleNodes("//bbb[#id='1']");
foreach (XmlNode n in nodes)
{
XmlNode parent = n.ParentNode;
parent.RemoveChild(n);
Console.WriteLine(n.OuterXml);
}
I would firstly suggest not using XmlDocument. It's old tech and has been superseded by XDocument, which gives you Linq2Xml and lots of explicit casting goodness when dealing with attributes etc.
Using the XDocument approach with Linq instead of XPath, it's quite a lot easier to work this problem:
var doc=XDocument.Load("file.xml");
var elToRemove = doc.Root.Elements("bbb").Single(el => (int)el.Attribute("id") == 1);
elToRemove.Remove();
Console.WriteLine(doc.ToString()); //no <bbb id="1">
Console.WriteLine(elToRemove.ToString()); //the full outer text of the removed <bbb>

Parse Xml attributes via XmlDocument

Good day!
I try to parse Xml document:
structure:
<root>
<SelectedConfig name="configuration1"/>
<config name="configuration1">
<Column Id="0" name="111"/>
...
</root>
I try to parse it like this:
XmlNode configNameNode = _doc.SelectSingleNode("//SelectedConfig");
if (configNameNode != null)
{
string configName = configNameNode.Attributes["name"].Value;
var config = _doc.SelectNodes("//config");
XmlNodeList columnNodes = _doc.SelectNodes("//config/Column");
foreach (XmlNode node in columnNodes)
{
var id = node.Attributes["Id"].Value;
var name = node.Attributes["name"].Value;
Tuple<string, String> numberOfColumnToColumnName = new Tuple<string, string>(id, name);
numberOfColumnToColumnNameTupleColl.Add(numberOfColumnToColumnName);
}
}
But, if i add:
<config name="configuration2">
I get N*2 nodes of //config/column.
How to select only one set of xml nodes- from configuration1 or 2?
Thank you!
You have multiple nodes "config", each with multiple child nodes "column".
Because all these nodes have the same name and only differ in their attributes, the function XmlNodeList columnNodes = _doc.SelectNodes("//config/Column"); will collect all "column" nodes of all "config"s.
Solution 1: rename config nodes to config_xxx, e.g. config_configuration1. But I think that's not what you want.
Solution 2: config = _doc.SelectNodes("//config"); already gets you a node list. Run a for each cfgEntry in config over the list, calling cfgEntry.SelectNodes("column") on each node. Then you will get only the column nodes of that single config node.
If you are trying to get the selected configuration, you can try the following code.
string xPath = string.format("//config[#name='{0}']/Column", configName);
var config = _doc.SelectNodes(xPath);

Search XML file for nodes with specific attribute value in .NET 2

I found answers for searching XML nodes using LINQ, but I am limited to C# with .NET 2.
I want to open a single XML file (~50Kb, all simple text) and search for all <Tool> nodes with attribute name having a specific value.
It seems like XmlDocument.SelectNodes() might be what I'm looking for, but I don't know XPath. Is this the right way and if so what would code look like?
You can use XPath in XmlDocument.SelectNodes such as: SelectNodes("//ElementName[#AttributeName='AttributeValue']")
Xml Sample:
<root>
<element name="value1" />
<element name="value2" />
<element name="value1" />
</root>
C# Sample:
XmlDocument xDoc = new XmlDocument();
// Load Xml
XmlNodeList nodes = xDoc.SelectNodes("//element[#name='value1']");
// nodes.Count == 2
Here you can find some additional XPath samples
think you could do something like that (well, rustic, but you've got the idea), using GetElementsByTagName
var myDocument = new XmlDocument();
myDocument.Load(<pathToYourFile>);
var nodes = myDocument.GetElementsByTagName("Tool");
var resultNodes = new List<XmlNode>();
foreach (XmlNode node in nodes)
{
if (node.Attributes != null && node.Attributes["name"] != null && node.Attributes["name"].Value == "asdf")
resultNodes.Add(node);
}

Get All node name in xml in silverlight

i created one xml like this
<names>
<name>
nixon
</name>
</names>
i want iterate each node name by foreach loop or any other loop in silverlight using xdocument.
how can i get this node name?
You can use the DescendantsAndSelf() method of XElement to get all the nodes and their names.
foreach (XElement child in doc.Root.DescendantsAndSelf())
{
Console.WriteLine(child.Name.LocalName);
}
DescendantsAndSelf() Returns a collection of elements that contain this element, and all descendant elements of this element, in document order.
With LinqToXml:
var xDoc = XDocument.Parse(mySmlString);
var names = xDoc.Root.Elements("name").Select(x=> x.Value.Trim()).ToArray();
foreach (var name in names)
{
System.Console.WriteLine(name);
}

XPath and attributes

I'm trying to traverse an XML document and select certain node attributes. The XML is dynamically generated.
<?xml version="1.0" encoding="ISO-8859-1"?>
<streams>
<stream>
<title>+23 (Panama)</title>
<info resolution="768x420" bitrate="1000kbps"/> ----- Need These
<swfUrl>http://www.freeetv.com/script/mediaplayer/player.swf</swfUrl>
<link>rtmp://200.75.216.156/live/</link>
<pageUrl>http://www.freeetv.com/</pageUrl>
<playpath>livestream</playpath>
<language>Music</language>
<advanced></advanced>
</stream>
</streams>
The code that I'm trying to use with zero luck and Visual Studio saying "No you're wrong. Try 600 more times" is
xDoc.Load("http://127.0.0.1/www/xml.php");
XmlNodeList nodes = xDoc.SelectNodes("/streams/stream");
foreach (XmlNode xn in nodes)
{
ListViewItem lvi = listView1.Items.Add(xn["title"].InnerText);
lvi.SubItems.Add(xn["swfUrl"].InnerText);
lvi.SubItems.Add(xn["link"].InnerText);
lvi.SubItems.Add(xn["pageUrl"].InnerText);
lvi.SubItems.Add(xn["playpath"].InnerText);
lvi.SubItems.Add(xn["language"].InnerText);
lvi.SubItems.Add(xn["advanced"].InnerText);
lvi.SubItems.Add(xn["//info/#resolution"].Value);
}
Please tell me oh wise ones what am I doing wrong?
If you want to select node's attribute using XPath you should use SelectSingleNode method, e.g.:
xn.SelectSingleNode("info/#resolution").Value
To select resolution attribute of your last node you need to use:
xn["info"].Attributes["resolution"].Value
Alternatively, you can try LINQ to XML for the same results (I find its API easier to use):
var doc = XDocument.Parse("http://127.0.0.1/www/xml.php");
foreach (var d in doc.Descendants("stream"))
{
ListViewItem lvi = listView1.Items.Add(d.Element("title").Value);
lvi.SubItems.Add(d.Element("swfUrl").Value);
// ...
vi.SubItems.Add(d.Element("info").Attribute("resolution").Value);
}
Here is an example of LINQ to XML to extract attributes from the entire document of a particular attribute name OR list of attribute names.
var xml = XElement.Parse("http://127.0.0.1/www/xml.php");
// find all attributes of a given name
var attributes = xml
.Descendants()
.Attributes("AttributeName")
// find all attributes of multiple names
var attributes = xml
.Descendants()
.Attributes()
.Where(a => ListOfAttribNames.Contains(a.Name.LocalName))
Replace:
lvi.SubItems.Add(xn["//info/#resolution"].Value);
with:
lvi.SubItems.Add(xn.SelectSingleNode("info/#resolution").Value);

Categories