Streamlining display of xml node attributes (array approach)
Your XML file snippet's syntax isn't correct. Each node has to show its node name after the opening bracket <SomeNode ...>
, but this nodename cannot be followed immediately by an equals character =
indicating always a following attribute assignment.
Therefore I built a wellformed xml structure to be able to illustrate a working MCV Example choosing to ("re")name the individual nodes <User ...>
followed by UserName
and weekday attributes (Monday="7:00" Tuesday="" ...
).
<?xml version="1.0" encoding="UTF-8"?>
<AllUsers>
<Team>
<User UserName="Jenny" Monday="7:00" Tuesday="7:30" Wednesday="0" Thursday="7:10" Friday="7:25" Saturday="6:00" Sunday="0"/>
<User UserName="Simon" Monday="8:20" Tuesday="7:45" Wednesday="7:45" Thursday="7:10" Friday="7:25" Saturday="7:00" Sunday="0"/>
<User UserName="Jenny2" Monday="8:00" Tuesday="8:30" Wednesday="8:00" Thursday="7:10" Friday="7:25" Saturday="0" Sunday="0"/>
</Team>
</AllUsers>
Example code
Based on this assumed example structure (loaded here via .LoadXML
), I demonstrate how to streamline code getting attributes via a NodeList loop based on the following xml content.
In order to allow a quickly reproducible example, I didn't refer to an external file via .Load
, but to a pure string content (received by help function getContent()
) loaded via .LoadXML
. Of course loading an external file needs the following syntax: xDoc.Load strTeamXMLPath
. - Btw several parts of the original code aren't clear, e.g. I don't know what's behind .LoadDocument
Sub GetAttributes()
Dim xdoc As MSXML2.DOMDocument60 ' early binding needs reference to Microsoft 'XML, v6.0'
Set xdoc = New MSXML2.DOMDocument60
If xdoc.LoadXML(getContent()) Then
Dim users As MSXML2.IXMLDOMNodeList
Set users = xdoc.SelectNodes("//Team/User") ' nodelist is zero-based
ReDim tmp(1 To users.Length, 1 To 8)
Dim i As Long
For i = 1 To users.Length
Dim j As Long
For j = 1 To users(i - 1).Attributes.Length
'assign to 1-based 2-dim tmp array
'(whereas users nodelist incl. node attributes list are zero-based!)
tmp(i, j) = users(i - 1).Attributes(j - 1).Text
'Debug.Print i & "." & j, tmp(i, j) ' optional display in VB Editor's immediate window
Next
Debug.Print i, Join(Application.Index(tmp, i, 0), "|")
Next i
Else ' XML Parse Error
Debug.Print getParseError(xdoc)
End If
' write tmp to any target
With Sheet1 ' << change to your project's sheet Code(Name)
' 'a) write captions starting from cell M1 (optional)
' For i = 1 To UBound(tmp, 2)
' .Range("M1").Offset(0, i - 1) = users(0).Attributes(i - 1).BaseName
' Next i
'write tmp results
.Range("M2").Resize(UBound(tmp, 1), UBound(tmp, 2)) = tmp
End With
End Sub
Additionaly you could test other syntax, e.g. for the 1st user (Jenny) to get the Monday
attribute:
Debug.Print users(0).Attributes.getNamedItem("Monday").BaseName ' "Monday"
Debug.Print users(0).Attributes.getNamedItem("Monday").Text ' 7:00
Debug.Print xdoc.DocumentElement.SelectSingleNode("Team/User[1]/@Monday").Text ' 7:00
Help functions
Function getContent()
gets an assumed minimal, but wellformed xml string content as described above replacing the unknown structure of OP's external file content.
Function getContent() As String
Dim tmp As String
tmp = "<?xml version=""1.0"" encoding=""UTF-8""?>" & vbNewLine
tmp = tmp & "<AllUsers>" & vbNewLine & " <Team>" & vbNewLine & _
vbTab & "<User UserName=""Jenny"" Monday=""7:00"" Tuesday=""7:30"" Wednesday=""0"" Thursday=""7:10"" Friday=""7:25"" Saturday=""6:00"" Sunday=""0""/>" & vbNewLine & _
vbTab & "<User UserName=""Simon"" Monday=""8:20"" Tuesday=""7:45"" Wednesday=""7:45"" Thursday=""7:10"" Friday=""7:25"" Saturday=""7:00"" Sunday=""0""/>" & vbNewLine & _
vbTab & "<User UserName=""Jenny2"" Monday=""8:00"" Tuesday=""8:30"" Wednesday=""8:00"" Thursday=""7:10"" Friday=""7:25"" Saturday=""0"" Sunday=""0""/>" & vbNewLine & _
" </Team>" & vbNewLine & "</AllUsers>"
getContent = tmp
Debug.Print getContent
End Function
Function getParseError(xdoc As MSXML2.DOMDocument60) As String
Dim xPE As MSXML2.IXMLDOMParseError
Set xPE = xdoc.parseError
With xPE
getParseError = "Load Error " & .ErrorCode & " XML File " & vbCrLf & _
Replace(.Url, "file:///", "") & vbCrLf & vbCrLf & _
xPE.reason & _
"Source Text: " & .srcText & vbCrLf & vbCrLf & _
"Line No: " & .Line & vbCrLf & _
"Line Pos: " & .linepos & vbCrLf & _
"File Pos: " & .filepos & vbCrLf & vbCrLf
End With
End Function