How do i Check if a xml Sibling has attributes? - c#

My program is doing weird stuff if i delete one of my Attributes because it is not able to handle Siblings without Attributes. Now i googled for a while but i am not able to find a good way to check for attributes.
Whats the way you prefer checking for attributes?
while (FXMLNode != null)
{
if (FXMLNode.Name.ToLower() == "datei")
{
xmlInformationen oInfo = new xmlInformationen();
oInfo.Dateipfad = FXMLNode.InnerText;
if (FXMLNode.Attributes["checked"].Value.ToString() == "true")
oInfo.CheckBox = true;
else if (FXMLNode.Attributes["checked"].Value.ToString() == "false")
oInfo.CheckBox = false;
else if(FXMLNode == null)
oInfo.CheckBox = true;
else
oInfo.CheckBox = true;
lstAttribute.Add(oInfo);
iCounter++;
if (FXMLNode.NextSibling == null)
{
FXMLNode = FXMLNode.FirstChild;
}
else
{
FXMLNode = FXMLNode.NextSibling;
}
}
else
{
if (FXMLNode.NextSibling == null)
{
FXMLNode = FXMLNode.FirstChild;
}
else
{
FXMLNode = FXMLNode.NextSibling;
}
}
}

You are accessing the value of an attribute without knowing if the attribute exists or not. Rewrite your code to check for the attribute first:
oInfo.CheckBox = true;
if(FXMLNode == null) oInfo.CheckBox = true; //not sure why you set it to true here
else if (FXMLNode.HasAttribute("checked"))
{
if (FXMLNode.Attributes["checked"].Value.ToString() == "true")
oInfo.CheckBox = true;
else if (FXMLNode.Attributes["checked"].Value.ToString() == "false")
oInfo.CheckBox = false;
}
Please note that checking if the Xml element is null should be the first thing you do. If it's null then it surely won't have any attributes but you'll have an exception.

you can just check thats the attribute in not null like this
if (FXMLNode.Attributes["checked"]!=null)
and then check the value

Related

How to combine multiple IF statements in C#

I have some flawed logic here..my goal is if all of the fields have "" value then return true, otherwise return false. How can I fix this in C# ?
public bool CheckFieldsAreEmpty()
{
Driver.WaitForElementValueNull(smtpHostInputField);
if (smtpHostInputField.GetAttribute("value") == "")
return true;
Driver.WaitForElementValueNull(smtpPortInputField);
if (smtpPortInputField.GetAttribute("value") == "")
return true;
Driver.WaitForElementValueNull(usernameInputField);
if (usernameInputField.GetAttribute("value") == "")
return true;
Driver.WaitForElementValueNull(passwordInputField);
if (passwordInputField.GetAttribute("value") == "")
return true;
Driver.WaitForElementValueNull(senderInputField);
if (senderInputField.GetAttribute("value") == "")
return true;
Driver.WaitForElementValueNull(receiverInputField);
if (receiverInputField.GetAttribute("value") == "")
return true;
else return false;
I believe something like this should work. I couldn't find what class all of those variables belong to, but replace var with the proper class and I think this should work.
logic: Add all variables to a List, use a lambda function to return if all of the list match GetAttribute("value") == ""
// Replace var with class type, or parent
List<var> allFields = new List<var> { smtpHostInputField, smtpPortInputField, sernameInputField, passwordInputField, senderInputField, receiverInputField };
foreach (var field in allFields) { Driver.WaitForElementValueNull(field); }
return allFields.All(t => t.GetAttribute("value") == "");
To illustrate #madreflection’s (correct) suggestion from the comments, consider this code:
public bool CheckFieldsAreEmpty()
{
Driver.WaitForElementValueNull(smtpHostInputField);
if (smtpHostInputField.GetAttribute("value") != "")
return false;
Driver.WaitForElementValueNull(smtpPortInputField);
if (smtpPortInputField.GetAttribute("value") != "")
return false;
Driver.WaitForElementValueNull(usernameInputField);
if (usernameInputField.GetAttribute("value") != "")
return false;
Driver.WaitForElementValueNull(passwordInputField);
if (passwordInputField.GetAttribute("value") != "")
return false;
Driver.WaitForElementValueNull(senderInputField);
if (senderInputField.GetAttribute("value") != "")
return false;
Driver.WaitForElementValueNull(receiverInputField);
if (receiverInputField.GetAttribute("value") != "")
return false;
return true;
}
Of course, as #Daniel-Lord’s answer highlights, you can centralize this repetitive logic using either a loop or a LINQ query.
Another way to solve this would be to extract WaitForElementValueNull call and empty string check to a separate method. Something like that:
private static bool WaitForElementValueNullAndEmpty(InputFieldType inputField)
{
Driver.WaitForElementValueNull(inputField);
return inputField.GetAttribute("value") == "";
}
public bool CheckFieldsAreEmpty()
{
return WaitForElementValueNullAndEmpty(smtpHostInputField) ||
WaitForElementValueNullAndEmpty(smtpPortInputField) ||
WaitForElementValueNullAndEmpty(usernameInputField) ||
WaitForElementValueNullAndEmpty(passwordInputField) ||
WaitForElementValueNullAndEmpty(senderInputField) ||
WaitForElementValueNullAndEmpty(receiverInputField);
}
The code above will match the algorithm that was provided, however if you want to check if ALL the values is empty then || should be replaced with && (As it was noticed by Jeremy Caney)

If Session match string

I got a little problem. I got a if statement which says if Session isn't equal 3, then do something, and if that isn't true, then do something else. My problem is just, that it isn't working proberly.
I've already tried:
1)
if (Session["userrank"] != "3")
{
pnlAdmin.Visible = false;
}
else
{
pnlAdmin.Visible = true;
}
2)
if (Session["userrank"].ToString() != "3")
{
pnlAdmin.Visible = false;
}
else
{
pnlAdmin.Visible = true;
}
3)
if ((string)Session["userrank"] != "3")
{
pnlAdmin.Visible = false;
}
else
{
pnlAdmin.Visible = true;
}
4)
if (((string)Session["userrank"]) != "3")
{
pnlAdmin.Visible = false;
}
else
{
pnlAdmin.Visible = true;
}
but none of them seems to work. And i have already checked if there's a Session called userrank that is getting the result 3.
sorry for the "stupid" question. I'm kind of new to C# & ASP.net.
Best Regards,
Anton
Your code sets pnlAdmin.Visible = false; if whatever is in Session["userrank"] is not 3.
It sets pnlAdmin.Visible = true; if whatever is in Session["userrank"] is 3.
You said it is 3; therefore, the panel should be visible. And that seems to be what is happening.

Class using XmlReader is not grabbing XML data as expected

I have a class in my app that is not transforming my XML data as expected.
XML Data
Below is an excerpt of the XML. The file size can be between 2 GB and 3 GB, and the data is a representation of Mutual Funds. Each Fund usually has managers associated with it, but it's possible that there are none listed. A Fund in the data can have multiple ManagerDetail nodes or can have no ManagerDetail nodes. Each manager can have multiple CollegeEducation nodes or no CollegeEducation nodes.
<MutualFund>
<ManagerList>
<ManagerDetail>
<ManagerRole>M</ManagerRole>
<ManagerId>7394</ManagerId>
<ManagerTenure>3.67</ManagerTenure>
<StartDate>2011-09-30</StartDate>
<OwnershipLevel>6</OwnershipLevel>
<GivenName>Stephen</GivenName>
<MiddleName>M.</MiddleName>
<FamilyName>Kane</FamilyName>
<Gender>M</Gender>
<Certifications>
<CertificationName>CFA</CertificationName>
</Certifications>
<CollegeEducations>
<CollegeEducation>
<School>University of Chicago</School>
<Year>1990</Year>
<Degree>M.B.A.</Degree>
</CollegeEducation>
<CollegeEducation>
<School>University of California - Berkeley</School>
<Year>1985</Year>
<Degree>B.S.</Degree>
<Major>Business</Major>
</CollegeEducation>
</CollegeEducations>
</ManagerDetail>
</ManagerList>
</MutualFund>
C# Class
I've created a class that is called within a BackgroundWorker instance in another form. This class places the above data into the following table:
public static DataTable dtManagersEducation = new DataTable();
dtManagersEducation.Columns.Add("ManagerId");
dtManagersEducation.Columns.Add("Institution");
dtManagersEducation.Columns.Add("DegreeType");
dtManagersEducation.Columns.Add("Emphasis");
dtManagersEducation.Columns.Add("Year");
The method that places the XML data is set up like this. Basically, I have certain points where DataRows are created and completed, and certain XML data is to be placed into the available row as the data is read.
public static void Read(MainForm mf, XmlReader xml)
{
mainForm = mf;
xmlReader = xml;
while (xmlReader.Read() && mainForm.continueProcess)
{
if (xmlReader.Name == "CollegeEducation")
{
if (nodeIsElement())
{
drManagersEducation = dtManagersEducation.NewRow();
drManagersEducation["ManagerId"] = currentManager.morningstarManagerId;
}
else if (nodeIsEndElement())
{
dtManagersEducation.Rows.Add(drManagersEducation);
drManagersEducation = null;
}
}
else if (xmlReader.Name == "School")
{
if (nodeIsElement() && drManagersEducation != null)
{
string value = xmlReader.ReadElementContentAsString();
drManagersEducation["Institution"] = value;
}
}
else if (xmlReader.Name == "Year")
{
if (nodeIsElement() && drManagersEducation != null)
{
string value = xmlReader.ReadElementContentAsString();
drManagersEducation["Year"] = value;
}
}
else if (xmlReader.Name == "Degree")
{
if (nodeIsElement() && drManagersEducation != null)
{
string value = xmlReader.ReadElementContentAsString();
drManagersEducation["DegreeType"] = value;
}
}
else if (xmlReader.Name == "Major")
{
if (nodeIsElement() && drManagersEducation != null)
{
string value = xmlReader.ReadElementContentAsString();
drManagersEducation["Emphasis"] = value;
}
}
}
}
private static bool nodeIsElement()
{
return xmlReader.NodeType == XmlNodeType.Element;
}
private static bool nodeIsEndElement()
{
return xmlReader.NodeType == XmlNodeType.EndElement;
}
The result ends up with no data in the Emphasis or Year columns, which as you can see above, there are instances (plenty) that have data in these fields.
ManagerId Institution DegreeType Emphasis Year
5807 Yale University M.S.
9336 Yale University
7227 Yale University M.S.
Would you all happen to have some insight into what is going on?
Thanks
Edit: Answer
My sample XML data listed above has indented spaces, but the actual data that I was running through the XmlReader did not. As dbc has shown below, adding a variable bool readNext fixed my issues. As I understand it, if readNext is set to false when ReadElementContentAsString() is called, the XmlReader will not call Read() since my while loop condition now contains (!readNext || xmlReader.Read()). This prevents the two methods ReadElementContentAsString() and Read() to be called right after another, and thus, it will not skip over data.
Thanks to dbc!
The problem you are seeing is that the method XmlReader.ReadElementContentAsString moves the reader past the end element tag. If you then do xmlReader.Read() unconditionally right afterwards, the node immediately after the end element tag will be skipped. In the XML shown in your question, the node immediately after your end element tags is whitespace, so the bug isn't reproducible with your question. But if I strip the indentation (and hopefully your 2+GB XML file has no indentation), the bug becomes reproducible.
Also, in your question, I don't see where you actually read the <ManagerId>7394</ManagerId> tag. Instead you just take it from currentManager.morningstarManagerId (an undefined global variable). I reckon that's a typo in your question, and in your actual code you read this somewhere.
Here's a version of your method that fixes these problems and can be compiled and tested standalone:
public static DataTable Read(XmlReader xmlReader, Func<bool> continueProcess)
{
DataTable dtManagersEducation = new DataTable();
dtManagersEducation.TableName = "ManagersEducation";
dtManagersEducation.Columns.Add("ManagerId");
dtManagersEducation.Columns.Add("Institution");
dtManagersEducation.Columns.Add("DegreeType");
dtManagersEducation.Columns.Add("Emphasis");
dtManagersEducation.Columns.Add("Year");
bool inManagerDetail = false;
string managerId = null;
DataRow drManagersEducation = null;
bool readNext = true;
while ((!readNext || xmlReader.Read()) && continueProcess())
{
readNext = true;
if (xmlReader.NodeType == XmlNodeType.Element)
{
if (!xmlReader.IsEmptyElement)
{
if (xmlReader.Name == "ManagerDetail")
{
inManagerDetail = true;
}
else if (xmlReader.Name == "ManagerId")
{
var value = xmlReader.ReadElementContentAsString();
readNext = false;
if (inManagerDetail)
managerId = value;
}
else if (xmlReader.Name == "School")
{
var value = xmlReader.ReadElementContentAsString();
readNext = false;
if (drManagersEducation != null)
drManagersEducation["Institution"] = value;
}
else if (xmlReader.Name == "Year")
{
var value = xmlReader.ReadElementContentAsString();
readNext = false;
if (drManagersEducation != null)
drManagersEducation["Year"] = value;
}
else if (xmlReader.Name == "Degree")
{
var value = xmlReader.ReadElementContentAsString();
readNext = false;
if (drManagersEducation != null)
drManagersEducation["DegreeType"] = value;
}
else if (xmlReader.Name == "Major")
{
var value = xmlReader.ReadElementContentAsString();
readNext = false;
if (drManagersEducation != null)
drManagersEducation["Emphasis"] = value;
}
else if (xmlReader.Name == "CollegeEducation")
{
if (managerId != null)
{
drManagersEducation = dtManagersEducation.NewRow();
drManagersEducation["ManagerId"] = managerId;
}
}
}
}
else if (xmlReader.NodeType == XmlNodeType.EndElement)
{
if (xmlReader.Name == "ManagerDetail")
{
inManagerDetail = false;
managerId = null;
}
else if (xmlReader.Name == "CollegeEducation")
{
if (drManagersEducation != null)
dtManagersEducation.Rows.Add(drManagersEducation);
drManagersEducation = null;
}
}
}
return dtManagersEducation;
}

NullReferenceException was unhandled

I'm just getting the hang of Lightswitch, but I keep getting the null reference exception error when I'm trying to find out if a selected item in a datagrid contains the letters "CMP". I look all over the place but I think I'm doing something wrong. Here is my code for reference:
if(string.IsNullOrWhiteSpace(this.location.SelectedItem.locationID))
{
this.ShowMessageBox("test"); //not sure what to put there so I just made something up
}
else if (this.location.SelectedItem.locationID.Contains("CMP"))
{
this.FindControl("datePurchased").IsVisible = true;
this.FindControl("age").IsVisible = true;
this.FindControl("userList").IsVisible = true;
}
else
{
this.FindControl("datePurchased").IsVisible = false;
this.FindControl("age").IsVisible = false;
this.FindControl("userList").IsVisible = false;
}
I also tried
if(this.location.selecteditem.locationID != null)
if(string.IsNullOrEmpty)
but it always throws me the same error. Any help would be much appreciated!
I guss this.location or this.location.selecteditem may be null, So you got that error.
So please try this if condition instead of your if condition way
if(this.location != null && this.location.selecteditem !=null && this.location.selecteditem.locationID != null)
{
//Write your code here
}
So your final code look like
if(this.location == null && this.location.selecteditem ==null && this.location.selecteditem.locationID == null)
{
this.ShowMessageBox("test"); //not sure what to put there so I just made something up
}
else if (this.location.SelectedItem.locationID.Contains("CMP"))
{
this.FindControl("datePurchased").IsVisible = true;
this.FindControl("age").IsVisible = true;
this.FindControl("userList").IsVisible = true;
}
else
{
this.FindControl("datePurchased").IsVisible = false;
this.FindControl("age").IsVisible = false;
this.FindControl("userList").IsVisible = false;
}

Hide/Show radio buttons on a questionnaire application

I am doing an assignment involving the creation of a simple Quiz type form application. However, whenever I run the program, only the first answer shows for a multiple question and I cannot for the life of me figure out why.
This is the contstructor:
MultipleChoice dlg =
new MultipleChoice(
new Question("What is the capital of Zimbabwe?",
new Answer("Paris", false),
new Answer("Washington D.C.", false),
new Answer("Harare", true),
new Answer("Cairo", false),
new Answer("N'Djamena", false)));
if (dlg.ShowDialog() == DialogResult.OK)
{
if (dlg.Correct) MessageBox.Show("You got something right!");
else MessageBox.Show("You couldn't be more wrong");
}
And this is the Question Form Code:
private Question Q;
public MultipleChoice (Question q)
{
Q = q;
InitializeComponent();
textPrompt.Text = Q.Prompt;
if (Q.A != null)
{
radioA.Text = Q.A.Prompt;
}
else radioA.Hide();
if (Q.B != null)
{
radioB.Text = Q.B.Prompt;
}
radioB.Hide();
if (Q.C != null)
{
radioC.Text = Q.C.Prompt;
}
radioC.Hide();
if (Q.D != null)
{
radioD.Text = Q.D.Prompt;
}
radioD.Hide();
if (Q.E != null)
{
radioE.Text = Q.E.Prompt;
}
radioE.Hide();
}
public bool Correct
{
get
{
if (Q == null) return false;
if (Q.A != null && Q.A.Correct && radioA.Checked) return true;
if (Q.B != null && Q.B.Correct && radioB.Checked) return true;
if (Q.C != null && Q.C.Correct && radioC.Checked) return true;
if (Q.D != null && Q.D.Correct && radioD.Checked) return true;
if (Q.E != null && Q.E.Correct && radioE.Checked) return true;
return false;
}
}
Where have I gone wrong?
There is no else for any option after A:
if (Q.B != null)
{
radioB.Text = Q.B.Prompt;
}
radioB.Hide(); //This is **always** going to be called - hiding radioB :)
Should be:
if (Q.B != null)
radioB.Text = Q.B.Prompt;
else
radioB.Hide();

Categories