I'm using a loop of repetition in a collection of nodes, however the output and always the first input of the foreach ...
var all_accounts_elements = content.GetCollectionNode(
"//div[#class='box-list-item text-c js-list-item']");
foreach (HtmlNode account_element in all_accounts_elements)
{
//for debug only
var copy = account_element;
var account = new InstagramAccount();
//for debug only
var debug = copy.SelectSingleNode("//*[#class='title']");
Debug.WriteLine(debug.InnerText);
account.AccountName = account_element.SelectSingleNode("//*[#class='title']")
.InnerText.ToTilteCase().Trim();
account.AddedData = account_element.SelectSingleNode("//*[#class='sub']")
.InnerText.Trim();
account.Edit = account_element.SelectSingleNode("//*[#class='context-menu']")
.InnerText.Trim();
account.Message = account_element.SelectSingleNode("//*[#class='quick-info']")
.InnerText.Trim();
accountsList.Add(account);
}
Colection:
1st element:
2st element:
Output:
jonisbarcelos
jonisbarcelos
Your XPath selector is telling the HTMLAgilityPack to look into the entire document. Try looking at the descendants instead:
account.AccountName = account_element.SelectSingleNode("descendant::div[#class='title']")
.InnerText.ToTilteCase().Trim();
account.AddedData = account_element.SelectSingleNode("descendant::div[#class='sub']")
.InnerText.Trim();
account.Edit = account_element.SelectSingleNode("descendant::div[#class='context-menu']")
.InnerText.Trim();
account.Message = account_element.SelectSingleNode("descendant::div[#class='quick-info']")
.InnerText.Trim();
Related
I have a Xamarin (C#) project, where I am trying to loop through some XML, but for some reason my code is not working.
This is what I have now:
DeviceList = new List<DeviceInfo>();
string ResultStatus = "";
string ResultDevice = "";
var result = Encoding.Default.GetString(e.Result);
result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + result;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(result);
string xPathStatus = "ed_listdevices";
var nodes = xmlDoc.SelectNodes(xPathStatus);
foreach (XmlNode xNode in nodes) {
ResultStatus = xNode.SelectSingleNode("//status").InnerText;
ResultDevice = xNode.SelectSingleNode("//device").InnerText;
}
if (ResultStatus.ToLower() == "ok") {
XmlDocument deviceDoc = new XmlDocument();
deviceDoc.LoadXml(result);
var deviceNodes = deviceDoc.SelectNodes(xPathStatus + "/device");
//foreach(XmlNode dNode in deviceNodes) {
for (int i = 0; i < deviceNodes.Count; i++) {
DeviceList.Add(new DeviceInfo() {
DeviceID = deviceNodes[i].SelectSingleNode("//id").InnerXml,
DeviceName = deviceNodes[i].SelectSingleNode("//name").InnerXml,
DeviceExtraName = "",
DeviceOnlineStatus = deviceNodes[i].SelectSingleNode("//status").InnerXml,
Location = deviceNodes[i].SelectSingleNode("//address").InnerXml,
Time = deviceNodes[i].SelectSingleNode("//time").InnerXml
});
}
}
When I step though the code I get the "ResultStatus" and "ResultDevice" correctly, and when I get to the
for (int i = 0; i < deviceNodes.Count; i++)
the "deviceNodes" variable have a count of 91, and I can see all the individual xml elements that I am suppose to get from the webservice I am calling.
However, when I loop through deviceNodes[i] I only get values from the very first XML element (yes, the value of "i" does change). In other words, my DeviceList is filled with 91 entries with the same values.
Am I missing something obvious?? What am I doing wrong since this isn't working??
PS: I have also tried using a foreach (XmlNode node in deviceNodes) but the result was the same.
"//" in the selector tells it to search from the root node of the document. If you want to search locally under the "current" node, remove the "//"
I am trying to read a XML file from a URL.
The URL and file are fine, they hold currency rates.
When running the code 9 out of 10 times, no content comes back.
Here is the code:
XDocument doc = XDocument.Load("http://www.boi.org.il/currency.xml");
int currID = 0;
Dictionary<int, Currency> curr; // declares the dictionary
curr = new Dictionary<int, Currency>();
var data = from item in doc.Descendants("CURRENCY") // LINQ the informartion from the xml to data variable
select new
{
name = item.Element("NAME").Value,
country = item.Element("COUNTRY").Value,
currencyCode = item.Element("CURRENCYCODE").Value,
rate = Convert.ToDouble(item.Element("RATE").Value),
unit = Convert.ToDouble(item.Element("UNIT").Value),
change = Convert.ToDouble(item.Element("CHANGE").Value),
};
foreach (var xn in data) // run in foreach on the data that we read from the xml and put it in a currency variable into the dictionary
{
Currency currency = new Currency();
currency.Name = xn.name;
currency.Country = xn.country;
currency.CurrencyCode = xn.currencyCode;
currency.Rate = Convert.ToDouble(xn.rate);
currency.Unit = Convert.ToDouble(xn.unit);
currency.Change = Convert.ToDouble(xn.change);
curr.Add(currID, currency);
currID++;
}
foreach (KeyValuePair<int, Currency> entry in curr)
{
Console.WriteLine(entry.Value.CurrencyCode);
}
I have edited the code to see the output, I get nothing.
What am I doing wrong?
Thanks in advance.
#David Faiz It Works!
XmlDocument xDoc = new XmlDocument();
xDoc.Load(#"http://www.boi.org.il//currency.xml");
XmlNodeList xmllist = xDoc.GetElementsByTagName("CURRENCIES");
Console.WriteLine(xmllist.Count);
You have must add // slashes in the URL. That is why u got the 'xmllist.Count' as Zero.
Here's a quick refactor of your code..
XDocument doc = XDocument.Load(#"http://www.boi.org.il/currency.xml");
foreach (XElement elm in doc.Elements)
{
Currency currency = new Currency();
currency.Name = elm.Element("NAME").Value;
currency.Country = elm.Element("COUNTRY").Value;
currency.CurrencyCode = elm.Element("CURRENCYCODE").Value;
currency.Rate = Convert.ToDouble(elm.Element("RATE").Value);
currency.Unit = Convert.ToDouble(elm.Element("UNIT").Value);
currency.Change = Convert.ToDouble(elm.Element("CHANGE").Value);
MessageBox.Show(elm.Element("CURRENCYCODE").Value);
curr.Add(currID, currency);
currID++;
}
However, I'm not sure this addresses the underlying issue you're having..
You could include the System.Net namespace and initialize a XMLHttpRequest object and use the Response stream with the static XDocument.Load() method..
Good day!
I try to parse tree on test plan tfs 2010.
So, i can get Test Plan:
var planOld = helperOldProject.GetTestPlan("TestProject", 10); // 10- id of test plan
ITestManagementTeamProject project1 = helperNewProject.GetProject(sourceserverurl, sourceproject);
Then i create new Test Plan Programmatically:
//Create a Test Plan Programmatically
ITestPlan planNew = project1.TestPlans.Create();
planNew.Name = planOld.Name;
planNew.StartDate = DateTime.Now;
planNew.EndDate = DateTime.Now.AddMonths(2);
planNew.AreaPath = "TestArea";
planNew.Description = planOld.Description;
planNew.State = planOld.State;
// other attributes: plan.AreaPath, plan.Description,plan.State
planNew.Save();
And then i need to parse RootSuite tree:
var suiteOld = planOld.RootSuite;
// Parse Root:
IStaticTestSuite suiteNew = project1.TestSuites.CreateStatic();
suiteNew.Title = suiteOld.Title;
planNew.RootSuite.Entries.Add(suiteNew);
foreach (var tcc in suiteOld.TestCases)
{
var tc = helperOldProject.teamProject.TestCases.Find(tcc.Id);
var tc2 = helperNewProject.teamProject.TestCases.Create();
tc2.Description = tc.Description;
tc2.Owner = tc.Owner;
tc2.Title = tc.Title;
tc2.Save();
suiteNew0.Entries.Add(tc2);
planNew.Save();
}
And then i need to parse SubTree:
CreateSubTree(ref project1,ref planOld,ref planNew,ref helperOldProject,ref helperNewProject);
public static void CreateSubTree(ref ITestManagementTeamProject project1,ref ITestPlan planOld,
ref ITestPlan planNew,ref Helper helperOldProject,ref Helper helperNewProject)
{
Console.WriteLine("SubSuites.Count: " + planOld.RootSuite.SubSuites.Count);
foreach (ITestSuiteBase suiteOld in planOld.RootSuite.SubSuites)
{
IStaticTestSuite suiteNew = project1.TestSuites.CreateStatic();
// planNew.RootSuite.SubSuites.Add(suiteNew);
IStaticTestSuite staticSuiteOld = suiteOld as IStaticTestSuite;
foreach (ITestSuiteEntry tccOld in staticSuiteOld.TestCases)
{
suiteNew.Title = suiteOld.Title;
planNew.RootSuite.Entries.Add(suiteNew);
//planNew.RootSuite.SubSuites.Add(suiteNew);
var tc = helperOldProject.teamProject.TestCases.Find(tccOld.Id);
var tc2 = helperNewProject.teamProject.TestCases.Create();
tc2.Description = tc.Description;
tc2.Owner = tc.Owner;
tc2.Title = tc.Title;
tc2.Save();
suiteNew.Entries.Add(tc2);
}
Console.WriteLine(suiteOld.TestSuiteEntry);
}
}
So, i parse new one subtree element, but i know,that after that node i have another one node.Like this:
Root: element1,element2,element3 ...
--- Node1:element1,element2....
-------- Node2: element1,element2...
But planOld.RootSuite.SubSuites.Count==1; And i see elements only of Root and Node1.
And another problem is to create new sub tree:
This code doesnt works:
planNew.RootSuite.SubSuites.Add(suiteNew); // cannot add,remove item error.
Please, help me to parse it!
And why i cannot add sub node at tree?
Thank you!
This is how you can create a new test suite under a test plan
ITestManagementTeamProject teamProject = testManagementService.GetTeamProject(projectId);
ITestPlan testplan= teamProject.TestPlans.Find(testplanId);
IStaticTestSuite newSuite = teamProject.TestSuites.CreateStatic();
newSuite.Title = "new title";
testplan.RootSuite.Entries.Add(newSuite);
testplan.Save();
For the first question I dont really understand maybe you can explain more.
How would I go about getting the ID information using Linq. I'm trying to add them to an array of int.
<FactionAttributes>
<name>Player</name>
<id>0</id>
<relationModifier>1</relationModifier>
<relations>
<id0>100</id0>
<id1>50</id1>
<id2>50</id2>
<id3>50</id3>
<id4>50</id4>
<id5>50</id5>
</relations>
</FactionAttributes>
That is my XML.
Here is the code I'm using so far.
void InitFactions()
{
int count = 0;
string filepath = Application.dataPath + "/Resources/factiondata.xml";
XDocument factionXML = XDocument.Load(filepath);
var factionNames = from factionName in factionXML.Root.Elements("FactionAttributes")
select new {
factionName_XML = (string)factionName.Element("name"),
factionID_XML = (int)factionName.Element("id"),
factionRelations_XML = factionName.Element("relations")// Need to turn this into array.
};
foreach ( var factionName in factionNames)
++count;
foreach ( var factionName in factionNames)
{
Factions f = new Factions();
f.otherFactionsName = new string[count];
f.otherFactionsRelation = new int[count];
int others = 0;
f.FactionName = factionName.factionName_XML;
Debug.Log(factionName.factionRelations_XML);
// Adds Rivals, not self to other list.
foreach (var factionName2 in factionNames)
{
if (factionName.factionID_XML == factionName2.factionID_XML)
continue;
f.otherFactionsName[(int)factionName2.factionID_XML] = factionName2.factionName_XML;
// THIS IS WHERE IM ADDING THE RELATIONS IN //
f.otherFactionsRelation[(int)factionName2.factionID_XML] = factionName.factionRelations_XML[(int)factionName2.factionID_XML];
Debug.Log(f.FactionName + " adds: " + factionName2.factionName_XML);
++others;
}
}
}
I have made multiple attempts using nodes and what not. I can't seem to figure out the correct syntax.
XDocument doc = XDocument.Load(Path);
//To get <id>
var MyIds = doc.Element("FactionAttributes").Element("id").Value;
//To get <id0>, <id1>, etc.
var result = doc.Element("FactionAttributes")
.Element("relations")
.Elements()
.Where(E => E.Name.ToString().Contains("id"))
.Select(E => new { IdName = E.Name, Value = E.Value});
If you want array of ints replace the select with this
.Select(E => Convert.ToInt32(E.Value)).ToArray();
If you are just after the relations Ids use this simple query
var doc = XDocument.Load("c:\\tmp\\test.xml");
var ids = doc.Descendants("relations").Elements().Select(x => x.Value);
If you want the Id and the relations ids in one array use this
var id = doc.Descendants("id").Select(x=>x.Value).Concat(doc.Descendants("relations").Elements().Select(x => x.Value));
I have the following XML :
<LOCALCELL_V18 ID = "0x2d100000">
<MXPWR ID = "0x3d1003a0">100</MXPWR>
</LOCALCELL_V18>
<LOCALCELL_V18 ID = "0x2d140000">
<MXPWR ID = "0x3d1403a0">200</MXPWR>
</LOCALCELL_V18>
<LOCALCELL_V18 ID = "0x2d180000">
<MXPWR ID = "0x3d1803a0">300</MXPWR>
</LOCALCELL_V18>
I want to get the inner text of each <MXPWR>. however, it is not allowed to use ID# to locate the inner text since it is not always the same. here is my code:
XmlNodeList LocalCell = xmlDocument.GetElementsByTagName("LOCALCELL_V18");
foreach (XmlNode LocalCell_Children in LocalCell)
{
XmlElement MXPWR = (XmlElement)LocalCell_Children;
XmlNodeList MXPWR_List = MXPWR.GetElementsByTagName("MXPWR");
for (int i = 0; i < MXPWR_List.Count; i++)
{
MaxPwr_form_str = MXPWR_List[i].InnerText;
}
}
Any opinion will be appreciated.
I would use xpath. It was designed for just this sort of problem. Something like:
using System.Xml;
using System.Xml.XPath;
....
string fileName = "data.xml"; // your file here
XPathDocument doc = new XPathDocument(fileName);
XPathNavigator nav = doc.CreateNavigator();
// Compile an xpath expression
XPathExpression expr = nav.Compile("./LOCALCELL_V18/MXPWR");
XPathNodeIterator iterator = nav.Select(expr);
// Iterate on the node set
while (iterator.MoveNext())
{
string s = iterator.Current.Value;
}
When I run this on your XML file (wrapped in a root node) I get:
s = 100
s = 200
s = 300
I would use XLinq:
using System.Xml.Linq;
var xDoc = XDocument.Load("data.xml");
var mxpwrs = xDoc.Descendants("MXPWR");
foreach (var mxpwr in mxpwrs)
{
Console.WriteLine(mxpwr.Value);
}