[RESOLVED] XML Find Max Value in Specific Attributes
I am trying to scan my XML code in order to find the max value in various attributes. I am looking to create a Subroutine with maybe a for loop or something that can look at the UID="" and UserID="" Attributes and have it return the Max Value out of those 2 attributes since I am using NextUID Num="" Attribute to provide the next Unique User ID number when creating a new Department or UserID for an actual User account in my XML file.
Note: This is just an app I am designing for practice as I am an intermediate/begging programmer, so I'm not worried about the content that is inside my XML code as it's all false information and doesn't really represent a specific person. I have hidden all of the passwords in this post to avoid comments for hashing the passwords, etc. I will do that when I redesign the app for an actual app I am prepping to build once I get this one in working order.
I will provide my XML code for review to see if anyone has some advice. I am not using classes to send information to and do the work, so I'm using basic Subroutines, and some functions and am sharing between files when needed. I am going to redesign and build this app that will utilize classes there (still need to figure out how to build classes to do the work and simplify the code). For now I'm just trying to learn as much as I can and am eager to do so and am learning on my own, so please bare with me.
XML code:
Code:
<?xml version="1.0" encoding="utf-8"?>
<!--XML Database - <SortList Type="A-Z" />
<User Name="" UserID="" ActType="" Password="" LogoutTime="" Phone="" Email="" ExtraNotes="" />-->
<Records>
<LastDeptSelected Name="Admin" />
<Departments>
<NextUID Num="019" />
<Department Name="Admin" UID="000" SortBy="UID" Members="1">
<User Name="Admin" UserID="001" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Administrator" />
</Department>
<Department Name="Engineering" UID="002" SortBy="A-Z" Members="1">
<User Name="David Smith" UserID="003" ActType="Admin" Password="******" LogoutTime="20" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Administrator" />
<User Name="Michael Smith" UserID="004" ActType="User" Password="mike2020" LogoutTime="15" Phone="509-248-9588" Email="[email protected]" ExtraNotes="" />
</Department>
<Department Name="Controls" UID="005" SortBy="A-Z" Members="2">
<User Name="Russell Smith" UserID="006" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-55555" Email="[email protected]" ExtraNotes="Programmer" />
<User Name="Smith David" UserID="007" ActType="User" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Programmer" />
<User Name="Chris Smith" UserID="008" ActType="User" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Controls Tech" />
</Department>
<Department Name="Construction" UID="009" SortBy="UID" Members="1">
<User Name="Randy Smith" UserID="010" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Construction Manager VP" />
</Department>
<Department Name="Management" UID="011" SortBy="UID" Members="1">
<User Name="Michael Smith" UserID="012" ActType="Admin" Password="******" LogoutTime="5" Phone="555-555-5555" Email="[email protected]" ExtraNotes="" />
</Department>
<Department Name="Shipping" UID="013" SortBy="UID" Members="1">
<User Name="Jody Smith" UserID="014" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Shipping" />
</Department>
<Department Name="Parts" UID="015" SortBy="A-Z">
<User Name="Brad Smith" UserID="016" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Parts Salesman" />
</Department>
<Department Name="CAD" UID="017" SortBy="A-Z">
<User Name="Jackson Johnson" UserID="018" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="CAD Engineer" />
</Department>
</Departments>
</Records>
I have written some code for managing the NextUID number and formatting it as well as counting the number of User accounts there and displaying that onthe screen. I am wanting to find the MAX number before this code, but in the same Subroutine to be able to create the NextUID number based on that Max value and adding 1 to it, instead of the app just creating the next number as I'm doing here (because if a user is removed, I want to keep the number count down as much as possible and if the value gets deleted somehow, I want it to have the ability to create it on its own if that makes sense.
Code:
Public Sub Next_UID()
Dim UIDList As XmlNodeList
Dim User_xmld As New XmlDocument()
User_xmld.Load(DeptSelectAttsFile)
Dim UserXMLNode As XmlNode = User_xmld.SelectSingleNode("/Records/Departments/NextUID")
Dim Add_UID As Integer = +1
Dim NextUID As Integer
UIDList = User_xmld.GetElementsByTagName("NextUID")
Dim ReturnValue As New List(Of String)
If Main.lblActType.Text = "Admin" Then
For Each node As XmlNode In User_xmld.SelectNodes("//Records/Departments/Department/User")
ReturnValue.Add(node.Attributes("Name").Value)
Next
'--Count All Users and Return Value to Main Admin (on the lblMembers Label)
For i As Integer = 0 To ReturnValue.Count
'int = i
ReturnValue.Add(i)
lblUserID.Text = i.ToString
Next
End If
Try
For Each UID As XmlElement In UIDList
If UserXMLNode IsNot Nothing Then
'--Automatically add Next UserID number into textbox & grey out the box
txtUID.Text = UID.Attributes("Num").Value
txtUID.Enabled = False
'--Convert NextUID from an integer to a string & Add 1 to it
NextUID = Convert.ToInt32(UID.Attributes("Num").Value) + Add_UID
'--If the Next UserID is less than 100, format as a 3 digit number
If NextUID < 100 Then
UID.Attributes("Num").Value = NextUID.ToString("000")
NewDeptUID = NextUID.ToString("000")
Else
'--If the Next UserID number is greater than 100, just keep as an integer, no need to
'--Convert to a string
UID.Attributes("UID").Value = NextUID
NewDeptUID = NextUID
Exit For
End If
End If
Next
Catch ex As Exception
MessageBox.Show("Missing NextUID Number in Users.ULA File, Contact your Administrator.", "File Error")
'UserApplicationForm.lblNotification.Text = "An Error has occurred - Contact your Administrator"
Me.Close()
End Try
End Sub
Any help would be greatly appreciated as I'm getting frustrated.
Re: XML Find Max Value in Specific Attributes
I didn't even realize until now that the code was staring me right in the face for how I counted all of the Users!!!
this is what I came up with to find max value for UserID="" attributes. Now I just need to account for UID in the departments as well and compare them!
Code:
'--Find Max Value for UserID
For i As Integer = 0 To ReturnValue.Max
ReturnValue.Add(i)
txtUID.Text = i.ToString
Next
End If
Re: XML Find Max Value in Specific Attributes
Didn't even mean to figure out my own code, but I was super frustrated and kept at it. Then I realized that if ReturnValue.Count could count the attributes I needed, so why not try ReturnValue.Max to find the Maximum Value within the Attributes? It was just a hunch.
Maybe this will help someone else, so I'm going to leave this post, but mark it as resolved.
Code:
Dim UIDList As XmlNodeList
Dim User_xmld As New XmlDocument()
User_xmld.Load(DeptSelectAttsFile)
Dim UserXMLNode As XmlNode = User_xmld.SelectSingleNode("/Records/Departments/NextUID")
Dim Add_UID As Integer = +1
Dim NextUID As Integer
UIDList = User_xmld.GetElementsByTagName("NextUID")
Dim ReturnValue As New List(Of String)
If Main.lblActType.Text = "Admin" Then
'--Return UserID values for each User
For Each UserID As XmlNode In User_xmld.SelectNodes("//Records/Departments/Department/User")
ReturnValue.Add(UserID.Attributes("UserID").Value)
Next
'--Return UID values for each Department
For Each UID As XmlNode In User_xmld.SelectNodes("//Records/Departments/Department")
ReturnValue.Add(UID.Attributes("UID").Value)
Next
'--Return MAX value between UserID and UID for each User and Department
For i As Integer = 0 To ReturnValue.Max
ReturnValue.Add(i)
txtUID.Text = i.ToString
Next
End If
Thanks to anyone who may have came here to help and if you came for help, here you go hahaha
Re: XML Find Max Value in Specific Attributes
Alright, I was finally able to complete the 2 Subroutines to accomplish what I wanted. The NextUID will automatically correct itself now if it somehow gets removed, which happened to me today. In the event this happens, it will run through and figure out the MAX UID and UserID and between the two, return the MAX value. Then I add +1 to it (which will be the Next UID or UserID, depending on if a new user account is being created or a new department is being created.
here is the code
Code:
Public Sub Next_UID()
'--Need to revamp how the UID is created based off the new style of XML code (with attributes)
Dim UIDList As XmlNodeList
Dim User_xmld As New XmlDocument()
User_xmld.Load(DeptSelectAttsFile)
Dim UserXMLNode As XmlNode = User_xmld.SelectSingleNode("//Records/Departments/NextUID")
Dim Add_UID As Integer = +1
Dim NextUID As Integer
UIDList = User_xmld.GetElementsByTagName("NextUID")
Dim ReturnValue As New List(Of String)
If Main.lblActType.Text = "Admin" Then
Try
For Each UID As XmlElement In UIDList
If UID.Attributes("Num").Value <> "" Then
'--Automatically add Next UserID number into textbox & grey out the box
txtUID.Text = UID.Attributes("Num").Value
txtUID.Enabled = False
'--Convert NextUID from an integer to a string & Add 1 to it
NextUID = Convert.ToInt32(UID.Attributes("Num").Value) + Add_UID
'--If the Next UserID is less than 100, format as a 3 digit number
If NextUID < 100 Then
UID.Attributes("Num").Value = NextUID.ToString("000")
NewDeptUID = NextUID.ToString("000")
Else
'--If the Next UserID number is greater than 100, just keep as an integer, no need to
'--Convert to a string
UID.Attributes("UID").Value = NextUID
NewDeptUID = NextUID
Exit For
End If
Else
If UID.Attributes("Num").Value = "" Then
Dim confirm_msg As Integer
confirm_msg = MessageBox.Show("Missing the Value for Next UID in the Users File." _
& vbCrLf & "Do you want to create the next avaialble UID Automatically?", "Missing XML Attribute Value",
MessageBoxButtons.YesNo, MessageBoxIcon.Information)
If confirm_msg = vbYes Then
'--Greyout UID Textbox (So that it cannot be changed manually)
txtUID.Enabled = False
'--We need to close the Login Form, and make sure the 'Main' form is visible
Dim NextUIDNum As Integer = 0
NextUIDNum = intNextUID + Add_UID
CreateNextUIDNum()
NextUIDNum = intNextUID + Add_UID
'UID.Attributes("Num").Value = NextUIDNum
If NextUIDNum < 100 Then
'UID.Attributes("Num").Value = NextUIDNum.ToString("000")
NewDeptUID = NextUIDNum.ToString("000")
'--Save File
'User_xmld.Save(DeptSelectAttsFile)
'DeptSelection.Refresh_List()
txtUID.Text = NewDeptUID
NextUIDNum = NextUIDNum + Add_UID
NewDeptUID = NextUIDNum.ToString("000")
DeptSelection.lstDepts.SelectedItem = txtDeptName.Text
Else
'UID.Attributes("Num").Value = NextUIDNum
txtUID.Text = NewDeptUID + Add_UID
NextUIDNum = NextUIDNum + Add_UID
NewDeptUID = NextUIDNum
'--Save File
'User_xmld.Save(DeptSelectAttsFile)
'DeptSelection.Refresh_List()
DeptSelection.lstDepts.SelectedItem = txtDeptName.Text
End If
ElseIf confirm_msg = vbNo Then
MessageBox.Show("You need to create a new UID Number", "Missing NextUID Number")
Me.Close()
End If
End If
End If
Next
Catch ex As Exception
MessageBox.Show("Missing NextUID Number in Users.ULA File, Contact your Administrator.", "File Error")
'UserApplicationForm.lblNotification.Text = "An Error has occurred - Contact your Administrator"
Me.Close()
End Try
End If
End Sub
Public Sub CreateNextUIDNum()
Dim User_xmld As New XmlDocument()
User_xmld.Load(DeptSelectAttsFile)
Dim ReturnValue As New List(Of String)
If Main.lblActType.Text = "Admin" Then
'--Return UserID values for each User
For Each UserID As XmlNode In User_xmld.SelectNodes("//Records/Departments/Department/User")
ReturnValue.Add(UserID.Attributes("UserID").Value)
Next
'--Return UID values for each Department
For Each UID As XmlNode In User_xmld.SelectNodes("//Records/Departments/Department")
ReturnValue.Add(UID.Attributes("UID").Value)
Next
'--Return MAX value between UserID and UID for each User and Department
For i As Integer = 0 To ReturnValue.Max
ReturnValue.Add(i)
intNextUID = i.ToString
strNextUID = i
Next
End If
End Sub
Re: [RESOLVED] XML Find Max Value in Specific Attributes
Alternative using XElement and LINQ
Your sample data
Code:
Dim xe As XElement
' xe = XElement.Load("path / URI here")
'for test use literal
xe = <Records>
<LastDeptSelected Name="Admin"/>
<Departments>
<NextUID Num="019"/>
<Department Name="Admin" UID="000" SortBy="UID" Members="1">
<User Name="Admin" UserID="001" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Administrator"/>
</Department>
<Department Name="Engineering" UID="002" SortBy="A-Z" Members="1">
<User Name="David Smith" UserID="003" ActType="Admin" Password="******" LogoutTime="20" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Administrator"/>
<User Name="Michael Smith" UserID="004" ActType="User" Password="mike2020" LogoutTime="15" Phone="509-248-9588" Email="[email protected]" ExtraNotes=""/>
</Department>
<Department Name="Controls" UID="005" SortBy="A-Z" Members="2">
<User Name="Russell Smith" UserID="006" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-55555" Email="[email protected]" ExtraNotes="Programmer"/>
<User Name="Smith David" UserID="007" ActType="User" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Programmer"/>
<User Name="Chris Smith" UserID="008" ActType="User" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Controls Tech"/>
</Department>
<Department Name="Construction" UID="009" SortBy="UID" Members="1">
<User Name="Randy Smith" UserID="010" ActType="Admin" Password="******" LogoutTime="60" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Construction Manager VP"/>
</Department>
<Department Name="Management" UID="011" SortBy="UID" Members="1">
<User Name="Michael Smith" UserID="012" ActType="Admin" Password="******" LogoutTime="5" Phone="555-555-5555" Email="[email protected]" ExtraNotes=""/>
</Department>
<Department Name="Shipping" UID="013" SortBy="UID" Members="1">
<User Name="Jody Smith" UserID="014" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Shipping"/>
</Department>
<Department Name="Parts" UID="015" SortBy="A-Z">
<User Name="Brad Smith" UserID="016" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="Parts Salesman"/>
</Department>
<Department Name="CAD" UID="017" SortBy="A-Z">
<User Name="Jackson Johnson" UserID="018" ActType="Admin" Password="******" LogoutTime="15" Phone="555-555-5555" Email="[email protected]" ExtraNotes="CAD Engineer"/>
</Department>
</Departments>
</Records>
And code to set next
Code:
Dim nUID As Integer
Dim nUserID As Integer
nUID = (From el In xe.Descendants
Where Integer.TryParse(el.@UID, Nothing)
Select Integer.Parse(el.@UID)).Max + 1
nUserID = (From el In xe.Descendants
Where Integer.TryParse(el.@UserID, Nothing)
Select Integer.Parse(el.@UserID)).Max + 1
xe.<Departments>.<NextUID>.@Num = {nUID, nUserID}.Max.ToString
Re: [RESOLVED] XML Find Max Value in Specific Attributes
I will give that a try also and see how it works. Thanks for the information! It's always good to know other ways of doing things. I really appreciate it. I'll let you know how it works.