For example in the xml below if I have the id attribute is it possible to get its corresponding reportid attribute in C#
The xml code:
<node text=" Acid Level versus Flowmeters" nodetype="1" reportid="118" id="626" />
<node text="Level versus Flowmeters" nodetype="1" reportid="119" id="627" />
<node text=" Bulk Levels" nodetype="1" reportid="120" id="629" />
<node text="Caustic and HCL" nodetype="1" reportid="121" id="630" />
the c# code:
string XMLFile = ConfigurationManager.AppSettings["XMLReportTreePath"];
XElement sitemap = XElement.Load(XMLFile);
XAttribute xatt = sitemap.Attribute(reportid); // where id = 630
Thanks
Assuming your xml document has a root node:
var reportid = sitemap.Descendants("node")
.Where(el => el.Attribute("id").Value == "630")
.Select(el => el.Attribute("reportid").Value)
.FirstOrDefault();
// or, lookup of all reportid by id
var lookup = sitemap.Descendants("node")
.ToDictionary(el => el.Attribute("id").Value, el => el.Attribute("reportid").Value);
Something like this ?
foreach (XmlNode chldNode in node.ChildNodes)
{
**//Read the attribute ID**
if (chldNode.ID== 630)
{
string reportid= chldNode.Attributes["reportid"].Value;
}
}
//just one example, but from what i could understand its something like this that you want
Related
Is there a way we can sort xmlnodes based on attribute values? The point is that every child node has a different name, despite it, I want to sort them by attribute.
E.g.
<Doc>
<mar_03 data="03">
<Mattina_Turno_1 />
</mar_03>
<dom_01 data="01">
<Mattina_Turno_1 />
</dom_01>
<mer_04 data="04">
<Mattina_Turno_1 />
<Mattina_Turno_2 />
</mer_04>
</Doc>
Should become
<Doc>
<dom_01 data="01">
<Mattina_Turno_1 />
</dom_01>
<mar_03 data="03">
<Mattina_Turno_1 />
</mar_03>
<mer_04 data="04">
<Mattina_Turno_1 />
<Mattina_Turno_2 />
</mer_04> </Doc>
How can I do it? After sorting obviously I want to overwrite the file.
This answer does not fix my problem since i can not define the node "item" since every my nodes are named differently.
Thanks, and please do not mark it as duplicate, because it is not!
Please try,
XDocument xdoc = XDocument.Load("File.xml");
var result = xdoc.Element("Doc")
.Elements()
.OrderBy(s => (int)s.Attribute("data"));
string xmlOutPut = string.Empty;
result.ToList().ForEach(a =>
{
xmlOutPut += a;
});
Where data and Doc is the parent element is your attribute according to your example. File.xml is your xml file name. You will get the sorted output in 'xmlOutPut'
or everything in a single Linq query,
XDocument xdoc = XDocument.Load("XMLFile2.xml");
string xmlOutPut = string.Empty;
xdoc.Element("Doc")
.Elements()
.OrderBy(s => (int)s.Attribute("data"))
.ToList().ForEach(a =>
{
xmlOutPut += a;
});
Sorting
XDocument xDoc = XDocument.Load("FileName.xml");
var res = xDoc.Element("Doc")
.Elements()
.OrderByDescending(c => (int) c.Attribute("data"));
Then to save it:
XDocument doc = new XDocument(new XElement("Doc", res));
doc.Save("FileName.xml");
I have got XML nodes as below.
...
<ParentNode>
<Node id="2343" name="some name" mode="Some Mode">
//Some child nodes here
</Node>
<Node id="2344" name="some other name" mode="Some Mode">
//Some child nodes here
</Node>
...
</ParentNode>
<ParentNode>
<Node id="2343" name="some name" mode="Some Other Mode">
//Some child nodes here
</Node>
<Node id="2344" name="some other name" mode="Some Mode">
//Some child nodes here
</Node>
</ParentNode>
....
What I need is
id name distinct-mode-count
--------------------------------------------
2343 some name 2
2344 some other name 1
I have tried below to get this.
XElement myXML = XElement.Load(filePath);
IEnumberable<XElement> parentNodes = myXML.Descendants("ParentNode");
var nodeAttributes = parentNodes.Select(le => le.Descendants("Node")
.GroupBy(x => new {
id = x.Attribute("id").Value,
name = x.Attribute("name").Value
}).Select(g => new {
id = g.Key.id,
name = g.Key.name,
distinct_mode_count = // This is where I am stuck
}));
I am not sure how to get distinct_mode_count in the above query.
Edit
I need distinct attribute value count for attribute "mode", regardless of which ParentNode they are in.
Assuming you want the count of the distinct "mode" attribute values within the nodes with the same ID/name, you just need to project from each element in the group to the mode, then take the distinct sequence of those modes, then count it:
You just need to take the count of the group, and also use SelectMany to "flatten" your parent nodes. (Or just use myXml.Descendants("Node") to start with.)
Short but complete example which gives your desired results:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XElement myXML = XElement.Load("test.xml");
IEnumerable<XElement> parentNodes = myXML.Descendants("ParentNode");
var nodeAttributes = parentNodes
.SelectMany(le => le.Descendants("Node"))
.GroupBy(x => new {
Id = x.Attribute("id").Value,
Name = x.Attribute("name").Value
})
.Select(g => new {
g.Key.Id,
g.Key.Name,
DistinctModeCount = g.Select(x => x.Attribute("mode").Value)
.Distinct()
.Count()
});
foreach (var item in nodeAttributes)
{
Console.WriteLine(item);
}
}
}
Alternatively:
XElement myXML = XElement.Load("test.xml");
var nodeAttributes = myXML
.Descendants("Node")
.GroupBy(...)
// Remaining code as before
I have an XML file which is like below:
<CPageDataXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<control id="busRowOAppr2EIDLookUpUserControl" controltype="business">
<field controlvaluetype="single" key="busRowOAppr2EIDLookUpUserControl_txtEID">
<valuefield value="709227">E8 - John Doe</valuefield>
</field>
<field controlvaluetype="hidden_single" key="busRowOAppr2EIDLookUpUserControl_txtEID_Email">
<valuefield value="_JohnDoe#Wonder.com">emailid</valuefield>
</field>
</control>
<control id="busDelegationFromDate123" controltype="business">
<field controlvaluetype="single" key="txtCalanderDateWithImage_UserControl">
<valuefield value="" />
</field>
</control>
</CPageDataXML>
I want to read the value of the valuefield where control id="busRowOAppr2EIDLookUpUserControl"
The C# code is:
This is the code for loading the XML:
XmlDocument xPagedata=new XmlDocument();
XmlNode xnodePagedata = null;
xPagedata.LoadXml(strPageData);
This is the code for SelectSingleNode:
string a = xnodePagedata.SelectSingleNode(//Control[#id='busRowOAppr2EIDLookUpUserControl']).Attributes["Value"].Value;
I have tried to use SelectSingleNode(string) but that is giving me a null reference exception. Kindly suggest how should I go about this one. I am an absolute beginer on XML.
One possible way using the same approach :
string a =
xnodePagedata.SelectSingleNode("//control[#id='busRowOAppr2EIDLookUpUserControl']/field/valuefield/#value")
.Value;
UPDATE :
In case there are multiple <valuefield> in one <control> and you want all values, use SelectNodes() for example :
var values =
xPagedata.SelectNodes("//control[#id='busRowOAppr2EIDLookUpUserControl']/field/valuefield/#value");
foreach (XmlNode value in values)
{
Console.WriteLine(value.Value);
}
You can use XDocument : use Descendants("control") to get all controls then filter them using the Where clause then use SelectMany to get a flattened collection of values of valuefield.
XDocument doc = XDocument.Load(filepath);
var result = doc.Descendants("control")
.Where(i => (string)i.Attribute("id") == "busRowOAppr2EIDLookUpUserControl")
.SelectMany(i => i.Descendants("valuefield")
.Select(j => j.Attribute("value")))
.ToList();
And this is the result:
result Count = 2
[0] {value="709227"}
[1] {value="_JohnDoe#Wonder.com"}
I tries to parse a XML file (get it from Dependacy Graph in VS 2012).
Here is sample of my .xml file
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes>
<Node Id="#101" Category="CodeSchema_ProjectItem" FilePath="$(ProgramFiles)\windows kits\8.0\include\um\unknwnbase.h" Label="unknwnbase.h" />
<Node Id="#103" Category="CodeSchema_ProjectItem" FilePath="$(ProgramFiles)\windows kits\8.0\include\shared\wtypesbase.h" Label="wtypesbase.h" />
in here, I needs to remove attribute "xmlns" from DirectedGraph.
here's my source to remove this
XmlNodeList rootNode = xmlDoc.GetElementsByTagName("DirectedGraph");
foreach (XmlNode node in rootNode)
{
node.Attributes.RemoveNamedItem("xmlns");
}
but this code doesn't work. If I don't delete this I can't select node like
XmlNodeList nodes = xmlDoc.DocumentElement.SelectNodes("/DirectedGraph/Nodes/Node");
What should I do?
If you like you can work with the namespace instead of removing the declaration:
var xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<DirectedGraph xmlns=""http://schemas.microsoft.com/vs/2009/dgml"">
<Nodes>
<Node Id=""#101"" Category=""CodeSchema_ProjectItem"" FilePath=""$(ProgramFiles)\windows kits\8.0\include\um\unknwnbase.h"" Label=""unknwnbase.h"" />
<Node Id=""#103"" Category=""CodeSchema_ProjectItem"" FilePath=""$(ProgramFiles)\windows kits\8.0\include\shared\wtypesbase.h"" Label=""wtypesbase.h"" />
</Nodes>
</DirectedGraph>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("d", "http://schemas.microsoft.com/vs/2009/dgml");
var nodes = doc.DocumentElement.SelectNodes("/d:DirectedGraph/d:Nodes/d:Node", manager);
Console.WriteLine(nodes.Count);
Use:
private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
if (!xmlDocument.HasElements)
{
XElement xElement = new XElement(xmlDocument.Name.LocalName);
xElement.Value = xmlDocument.Value;
foreach (XAttribute attribute in xmlDocument.Attributes())
xElement.Add(attribute);
return xElement;
}
return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
}
Taken from: How to remove all namespaces from XML with C#?.
You might also want to check out: XmlSerializer: remove unnecessary xsi and xsd namespaces.
Assuming I have an XmlDocument like this:
<xmlFile>
<details>
<code1>ADJ</code1>
<code2>ADC </code2>
<Shipment>
<foo></foo>
<bar></bar>
</Shipment>
<Shipment>
<foo></foo>
<bar></bar>
</Shipment>
</details>
<details>
<code1>ADJ</code1>
<code2>SCC </code2>
<Shipment>
<foo></foo>
<bar></bar>
</Shipment>
</details>
</xmlFile>
I need to process each in an xml file but only shipments that fall under the tags with a child node with a value of "ADC". So far I have:
// Assume there is an XmlDocument named xml
XmlNodeList details= xml.GetElementsByTagName("details");
foreach (XmlNode node in details)
{
if (node["code2"].InnerText == "ADC ")
{
// Get each shipment and process it accordingly.
}
}
I can't figure out what to do next. Thanks.
Assuming Data\Sample.xml contains xml as mentioned in the question,
Following is the XLINQ query
XElement root = XElement.Parse(File.ReadAllText(#"Data\Sample.xml"));
var adcShipment = root.Descendants().Where(e=>String.Equals(e.Value, "ADC "));
//next query for nodes/elements inside/next to ADC shipments
XPath can simplify your search for matches:
foreach (XmlNode node in xml.SelectNodes("/xmlFile/details[normalize-space(code2)='ADC']"))
{
string foo = node.SelectSingleNode("foo").InnerText;
string bar = node.SelectSingleNode("bar").InnerText;
}
I'm in the process of adding XPath parsing to this library: https://github.com/ChuckSavage/XmlLib/
I modified it so you can do this:
XElement root = XElement.Load(file);
var shipments = root.XPath("details[starts-with(*,'ADC')]/Shipment");
Long-hand that looks like:
var shipments = root.Elements("details")
.Where(x => x.Elements().Any(xx => ((string)xx).StartsWith("ADC")))
.Elements("Shipment");
This is the sort of thing you're after
XmlNodeList details = xml.GetElementsByTagName("details");
foreach (XmlNode node in details)
{
if (node["code2"].InnerText.Trim() == "ADC")
{
// Get each shipment and process it accordingly.
foreach(XmlNode shipment in node.SelectNodes("Shipment"))
{
var foo = shipment.SelectSingleNode("foo");
var bar = shipment.SelectSingleNode("bar");
}
}
}