How to parse tree from TFS Test Plan - c#

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.

Related

Repeat loop does not iterate over all elements

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();

Web-scrape project writing too much information

I'm trying to modify the code below to scrape jobs from www.itoworld.com/careers. The jobs are in a table format and return all the <'td> values.
I believe it comes from the line:
var parentnode = node.ParentNode.ParentNode.ParentNode.FirstChild.NextSibling
However, I want it to write:
<a class="std-btn" href="http://www.itoworld.com/office-manager/">Office Manager</a>
Currently it is writing
<a href='http://www.itoworld.com/office-manager/' target='_blank'>Office ManagerOffice & AdminCambridgeFind out more</a>
I plan on 'brute force' modifying the output to remove unnecessary extras but was hoping there is a smarter way to do this. Is there a way for example to remove the second and third ParentNode after they have been called? (So they do not get written?)
public string ExtractIto()
{
string sUrl = "http://www.itoworld.com/careers/";
GlobusHttpHelper ghh = new GlobusHttpHelper();
List<Links> link = new List<Links>();
bool Next = true;
int count = 1;
string html = ghh.getHtmlfromUrl(new Uri(string.Format(sUrl)));
HtmlAgilityPack.HtmlDocument hd = new HtmlAgilityPack.HtmlDocument();
hd.LoadHtml(html);
var hn = hd.DocumentNode.SelectSingleNode("//*[#class='btn-wrapper']");
var hnc = hn.SelectNodes(".//a");
foreach (var node in hnc)
{
try
{
var parentnode = node.ParentNode.ParentNode.ParentNode.FirstChild.NextSibling;
Links l = new Links();
l.Name = ParseHtmlContainingText(parentnode.InnerText);
l.Link = node.GetAttributeValue("href", "");
link.Add(l);
}
}
string Xml = getXml(link);
return WriteXml(Xml);
For completeness below is the definition of ParseHtmlContainingText
public string ParseHtmlContainingText(string htmlString)
{
return Regex.Replace(Regex.Replace(WebUtility.HtmlDecode(htmlString), #"<[^>]+>| ", ""), #"\s{2,}", " ").Trim();
}
You just need to create a "name node" and use that for your parse method.
I tested with this code and it worked for me.
var parentnode = node.ParentNode.ParentNode.ParentNode.FirstChild.NextSibling;
var nameNode = parentnode.FirstChild;
Links l = new Links();
l.Name = ParseHtmlContainingText(nameNode.InnerText);
l.Link = node.GetAttributeValue("href", "");

Parallel task on tree structure not complete

Very new to .NET task parallelism. The objective is walking through a tree structure, where each branch is composed of one parent node, one child node and one operation node(like a weight). And for each node, create an extension object and save it to db. I followed a possible duplicate conversation. But the observation is that the tree is not walked through completely. The process would exit early unexpectedly. Following is my code:
public void InitializeScheduleVariables_Parallel(IResource ANode, double aNumRequired, double aBatchRequired, double aAcceptProbability, AppContext aAppContext, bool ARecursively = true)
{
var LTasks = new List<Task>();
var LUser = aAppContext.LocalContext.User;
LTasks.Add(Task.Factory.StartNew(() =>
{
var LNewContext = new AppContext(new DbContext(new Context(LUser)));
var LNewRep = new ResourceRepository(LNewContext);
ANode = LNewRep.Get(ANode.Id);
ANode.ResourceInstance_Create(); // Create the ResourceInstance on the Resourse if it not already exists.
ANode.ResourceInstance.Required = aNumRequired;
ANode.ResourceInstance.ScheduleSource = ResourceInstance.ScheduleSourceEnum.Undefined;
ANode.ResourceInstance.ScheduleState = ResourceInstance.ScheduleStateEnum.Unscheduled;
ANode.ResourceInstance.ScheduleMode = ResourceInstance.ScheduleModeEnum.Undefined;
ANode.ResourceInstance.BatchRequired = aBatchRequired;
ANode.ResourceInstance.ProbabilityOfCompletion = aAcceptProbability;
ANode.ResourceInstance.Save();
}));
if (ARecursively)
{
foreach (AssemblyLink LAssembly in ANode.GetOutEdges())
{
LTasks.Add(Task.Factory.StartNew(() =>
{
// SET The Variables for the Production Operations AS WELL
IOperationResource LOperation = LAssembly.Operation;
if (LOperation != null)
{
var LNewContext = new AppContext(new DbContext(new Context(LUser)));
var LNewRep = new OperationResourceRepository(LNewContext);
LOperation = LNewRep.Get(LOperation.Id);
LOperation.ResourceInstance_Create(); // Create the ResourceInstance on the Resourse if it not already exists.
LOperation.ResourceInstance.Required = aNumRequired / LAssembly.OutputQuantity;
LOperation.ResourceInstance.BatchRequired = aBatchRequired / LAssembly.OutputQuantity;
LOperation.ResourceInstance.ScheduleSource = ResourceInstance.ScheduleSourceEnum.Undefined;
LOperation.ResourceInstance.ScheduleState = ResourceInstance.ScheduleStateEnum.Unscheduled;
LOperation.ResourceInstance.ScheduleMode = ResourceInstance.ScheduleModeEnum.Undefined;
LOperation.ResourceInstance.ProbabilityOfCompletion = aAcceptProbability;
LOperation.ResourceInstance.Save();
}
}));
LTasks.Add(Task.Factory.StartNew(() =>
{
// Recursively SET Child NODES
IResource LChildNode = LAssembly.Child;
double LNumRequired_Child = aNumRequired * LAssembly.InputQuantity / LAssembly.OutputQuantity;
double LNumBatchRequired_Child = LChildNode.Quantity * LAssembly.InputQuantity / LAssembly.OutputQuantity;
InitializeScheduleVariables_Parallel(LChildNode, LNumRequired_Child, LNumBatchRequired_Child, aAcceptProbability, aAppContext, ARecursively);
}));
}
}
Task.WaitAll(LTasks.ToArray());
}
Could anyone share some thought? Thank you.

Read XML file from URL, comes up empty

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..

Reading the XML values using LINQ

what is the best way of reading xml file using linq and the below code you will see that, I have three different loops and I feel like its not elegant or do I have options to retrofit the below code?
public static void readXMLOutput(Stream stream)
{
XDocument xml = new XDocument();
xml = LoadFromStream(stream);
var header = from p in xml.Elements("App").Elements("Application")
select p;
foreach (var record in header)
{
string noym = record.Element("nomy").Value;
string Description = record.Element("Description").Value;
string Name = record.Element("Name").Value;
string Code = record.Element("Code").Value;
}
var appRoles = from q in xml.Elements("App").Elements("Application").Elements("AppRoles").Elements("Role")
select q;
foreach (var record1 in appRoles)
{
string Name = record1.Element("Name").Value;
string modifiedName = record1.Element("ModifiedName").Value;
}
var memeber = from r in xml.Elements("App").Elements("Application").Elements("AppRoles").Elements("Role").Elements("Members")
select r;
foreach (var record2 in memeber)
{
string ExpirationDate = record2.Element("ExpirationDate").Value;
string FullName = record2.Element("FullName").Value;
}
}
UPDATED:
foreach (var record in headers)
{
..............
string Name1 = record.Attribute("Name").Value;
string UnmodifiedName = record.Attribute("UnmodifiedName").Value;
string ExpirationDate = record.Attribute("ExpirationDate").Value;
string FullName = record.Attribute("FullName").Value;
...............
}
Is that your actual code ? All those string variables you are assigning in the foreach loops only have a scope of one iteration of the loop. They are created and destroyed each time.
This may not work precisely in your case depending on the xml structure. Play around with it. Try it using LinqPad
var applications = from p in xml.Descendants("Application")
select new { Nomy = p.Element("nomy").Value
, Description = p.Element("Description").Value
, Name = p.Element("Name").Value
, Code = p.Element("Code").Value
};
var appRoles = from r in xml.Descendants("Role")
select new { Name = r.Element("Name").Value
, ModifiedName = r.Element("ModifiedName").Value
};
This answer is a hierarchical query.
var headers =
from header in xml.Elements("App").Elements("Application")
select new XElement("Header",
new XAttribute("noym", header.Element("nomy").Value),
new XAttribute("Description", header.Element("Description").Value),
new XAttribute("Name", header.Element("Name").Value),
new XAttribute("Code", header.Element("Code").Value),
from role in header.Elements("AppRoles").Elements("Role")
select new XElement("Role",
new XAttribute("Name", role.Element("Name").Value),
new XAttribute("ModifiedName", role.Element("ModifiedName").Value),
from member in role.Elements("Members")
select new XElement("Member",
new XAttribute("ExpirationDate", member.Element("ExpirationDate").Value),
new XAttribute("FullName", member.Element("FullName").Value)
)
)
);

Categories

Resources