I am struggling with code in C# for getting value depending on the first argument from XML:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="browser" value="chrome" />
<Parameter name="browserVersion" value="101.0"/>
<Parameter name="os" value="WIN11"/>
<Parameter name="build" value=""/>
</TestRunParameters>
</RunSettings>
I would like to check if the parameter name is browser then take its content from value.
I am able to get this values by SelectNodes("//#value") and node[0].Value but I am wondering if there is another way of getting those values without specifing the position. Here is my code:
var filename = #"../../../browser.runsettings";
var xmlDoc = new XmlDocument();
xmlDoc.Load(filename);
XmlNodeList node = xmlDoc.SelectNodes("//#value");
var browserValue = node[0].Value;
Thanks in advance for help
I think you should cycle thought them and check if the name is Browser and then use the value. Something like this should do it
foreach (XmlNode node in nodes)
{
if (node.Name != "Browser") continue;
browserValue = node.Value;
break;
}
You can also get single node by using .SelectSingleNode() instead of using .SelectNodes()
var filename = #"../../../browser.runsettings";
var xmlDoc = new XmlDocument();
xmlDoc.Load(filename);
XmlNode node = xmlDoc.SelectSingleNode("//#value");
var browserValue = node.Value;
Related
I have a string XML called doc that looks like this:
<equity location="New York", index=0>
<bucket date="20211009">
...
</bucket>
<parameters>
<parameter Key="ID">1234</parameter>
<parameter Key="A">6</parameter>
<parameter Key="B">22.5</parameter>
<parameter Key="C">12</parameter>
<parameter Key="BD">12,8,5</parameter>
</parameters>
</equity>
I am trying to get "pameter" for a specific key, let's say 'B'.
Using:
XmlDocument xmldoc = new XmlDocument();
xmmldoc.loadXML(doc.content);
Then browsing stackoverflow I have tried working around that line without success:
var key = xmldoc.SelectSingleNode("Descendant::parameters/parameter[#Key='B']").value;
The example you cited is working. Just Descendant:: is case sensitive I guess.
XmlNode node = xmldoc.SelectSingleNode("descendant::parameters/parameter[#Key='B']");
This does get you the node parameter that you are looking for, except the node.Value will return null.
In your case you may use node.InnerText or node.InnerXml to get the value.
I have an xml file that has a bunch of channels, and I want to append a channel category to every single one of them. Depending on what channel it is. I'm very new to this so please excuse me if this is an obvious error.
example:
<channel-category>Entertainment</channel-category>
or
<channel-category>News</channel-category>
I have tried the following:
string path;
string xmlfile = "/channels.xml";
path = Environment.CurrentDirectory + xmlfile;
if (exists("channelname1"))
{
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNode root = doc.DocumentElement;
XmlNode node = root.SelectSingleNode("list/channel[#id='channelname1'");
XmlNode category = doc.CreateElement("channel-category");
category.InnerText = "channelcataegorygoeshere";
node.AppendChild(category);
doc.DocumentElement.AppendChild(node);
}
else
{
Console.WriteLine("not found");
}
Console.ReadKey();
}
static bool exists(string channelname)
{
string path;
string xmlfile = "/channels.xml";
path = Environment.CurrentDirectory + xmlfile;
XDocument xmlDoc = XDocument.Load(path);
bool doesexists = (from data in xmlDoc.Element("list").Elements("channel")
where (string)data.Attribute("id") == channelname
select data).Any();
return doesexists;
}
but it's giving me the following error and I can't figure it out.. What am I doing wrong?
An unhandled exception of type 'System.Xml.XPath.XPathException' occurred in System.Xml.dll
Additional information: 'list/channel[#id='channelname1'' has an invalid token.
from this line
XmlNode node = root.SelectSingleNode("list/channel[#id='channelname1'");
My XML looks like this
<?xml version="1.0" encoding="UTF-8"?>
<list info="list">
<channel id="channelname1">
<display-name lang="en">channelname1</display-name>
<icon src="http://locationtologo.com/" />
<url>http://someurl.com</url>
</channel>
<channel id="channelname2">
<display-name lang="en">channelname2</display-name>
<icon src="http://locationtologo.com/" />
<url>http://someurl.com</url>
</channel>
<channel id="channelname3">
<display-name lang="en">channelname3</display-name>
<icon src="http://locationtologo.com/" />
<url>http://someurl.com</url>
</channel>
<channel id="channelname4">
<display-name lang="en">channelname4</display-name>
<icon src="http://locationtologo.com/" />
<url>http://someurl.com</url>
</channel>
</list>
You dont have closing bracket in list/channel[#id='channelname1'(HERE).
Moreover, you are actually trying to do following:
var doc = new XmlDocument();
doc.Load(Environment.CurrentDirectory + "\\channels.xml");
var nodes = doc.SelectNodes("list/channel[#id=\"channelname1\"]");
if (nodes != null)
{
foreach (XmlNode node in nodes)
{
var el = doc.CreateElement("channel-category");
el.InnerText = "SomeValue";
node.AppendChild(el);
}
}
bool doesexists = (from data in xmlDoc.Element("tv").Elements("channel")
where (string)data.Attribute("id") == channelname
select data).Any();
You are trying to reach the channel node where the id equals the channelname inside tv. The problem is that tv does not exist, the channels are inside this:
<list info="list">
Solution: either put the channels into tv, or use a selector appropriate to your current structure.
Why you are using tv instead of list thats why xml library not getting your path of your elements and throwing this error.
try this..
XmlNode node = root.SelectSingleNode("list/channel");
node.Attributes["id"].Value=="channelname1"?true:false;
My XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<something.logger>
<add key="LoggerId" value="8a2ff9ef-d144-4dcb-86d8-6ccaf44def20">
</add>
<add key="FederationId" value="00000000-0000-0000-0000-000000000000" />
</something.logger>
</configuration>
My code:
XmlDocument xml = new XmlDocument();
xml.Load(Some-Valid-Path);
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger");
I am trying to get the Guid (or value..) of value.
In the end i want to get the string "8a2ff9ef-d144-4dcb-86d8-6ccaf44def20"
Thanks !
Use # at the beginning of attribute name to reference an attribute in XPath. Then you need to cast each item in list as XmlAttribute :
XmlNodeList xnList = doc.SelectNodes("/configuration/something.logger/add[#key='LoggerId']/#value");
foreach (XmlAttribute n in xnList)
{
Console.WriteLine(n.Value);
}
Use /# to access attributes:
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger/add/#value");
This is my xml file
<profiles>
<profile id='8404'>
<name>john</name>
<name>mark</name>
</profile>
<profile id='8405'>
<name>john</name>
</profile>
</profiles>
and I want to select profiles where last "name" child value= john, the result should contains the profile with id=8405 only
what it the xpath that can evaluate this?
here is my trial:
var filterdFile = profilefileXML.XPathSelectElements("/profiles/profile[name[last()]='john']");
but it doesn't make sense.
Updated:
My trail is correct, there was only a syntax error in it. Thanks all
You can apply multiple indexing operations with successive [...]:
var doc = XDocument.Parse(xml); //the xml from your question
var node = doc.XPathSelectElement("/profiles/profile[name='john'][last()]");
Console.WriteLine(node.Attribute("id").Value); //outputs 8405
This will return the last profile element that contains the element name with a value of john.
If you on the other hand want to return all elements which last name element has a value of john, your XPath should work already:
var nodes = doc.XPathSelectElements("/profiles/profile[name[last()]='john']");
foreach (var node in nodes)
{
Console.WriteLine(node.Attribute("id").Value);
}
You can also try LINQ
XDocument xDoc = XDocument.Load("data.xml");
var matches = xDoc.Descendants("profile")
.Where(profile => XElement.Parse(profile.LastNode.ToString()).Value == "john");
And you can access the xml data with a foreach
foreach(XElement xEle in lastEle)
{
var xAttribute = xEle.Attribute("id");
if (xAttribute != null)
{
var id = xAttribute.Value;
}
var lastName = XElement.Parse(xEle.LastNode.ToString()).Value;
}
I have an XML file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<PathMasks>
<Mask desc="Masks_X1">
<config id="01" mask="88" />
<config id="03" mask="80" />
<config id="51" mask="85" />
</Mask>
<Mask desc="Masks_X2">
<config id="70" mask="1" />
<config id="73" mask="6" />
</Mask>
<Types>
<path id="01" desc="TC->PP1" />
<path id="02" desc="TC->PP2" />
<path id="03" desc="TC->PPn" />
</Types>
</PathMasks>
How to parse the file and get all the data of Mask_X1 as following:
id value
=====
01, 88
03, 80
51, 85
The .NET framework I am using is 2.0
As you're working with .Net 2.0 you won't have Linq and will therefore need to use XPath, this sample should help you out.
XmlDocument doc = new XmlDocument();
doc.Load(pathToXmlDoc);
XmlNode node = doc.SelectSingleNode("/PathMasks/Mask[#desc='Masks_X1']");
foreach (XmlNode config in node)
{
Console.WriteLine("{0}\t{1}",
config.Attributes["id"].Value,
config.Attributes["mask"].Value);
}
Using XmlDocument (slower, larger memory footprint, read/write, works the same way XML DOMs everywhere work):
XmlDocument d = new XmlDocument();
d.Load(filename);
string xpath = "/PathMasks/Mask[#desc='Mask_X1']/config"
foreach (XmlElement elm in d.SelectNodes(xpath))
{
Console.WriteLine(elm.GetAttribute("id"), elm.GetAttribute("desc"));
}
Using XPathDocument (faster, smaller memory footprint, read-only, weird API):
XPathDocument d = new XPathDocument(filename);
string xpath = "/PathMasks/Mask[#desc='Mask_X1']/config"
XPathNodeIterator iter = d.CreateNavigator().Select(xpath);
while (iter.MoveNext())
{
Console.WriteLine(iter.Current.GetAttribute("id"), iter.Current.GetAttribute("desc'));
}
I'm sure there's a perfectly good reason why there isn't a method of XPathNavigator that returns an IEnumerable<XPathNavigator> so that you can iterate over the results of an XPath query like a normal person, but I haven't been able to work it out.
Using Linq to XML :
XDocument doc = XDocument.Load(filename);
var query = from mask in doc.Root.Elements("Mask")
where mask.Attribute("desc").Value == "Masks_X1"
from config in mask.Elements("config")
select new
{
id = config.Attribute("id").Value,
value = config.Attribute("mask").Value
};
foreach(var mask in query)
{
Console.WriteLine("{0}\t{1}", mask.id, mask.value);
}
Use XDocument and query into it with Linq to XML
XDocument doc = XDocument.Load("file.xml");
var linqtoxml = from node in document.Descendants("Mask")
where (string)node.Attribute("desc").Value == "Masks_X1"
select node;
foreach (var mask in linqtoxml)
{
// pull data out of here into a structure of your choosing
}