I need to get the distinct attributes names from the XML using VBA.
this is my code.
sub test()
Dim XMLFile As Object
Dim XMLFileName As String
Set XMLFile = CreateObject("Microsoft.XMLDOM")
XMLFileName = "C:\Users\Input.xml"
XMLFile.async = False
XMLFile.Load (XMLFileName)
XMLFile.validateOnParse = False
Dim mainnode As Object
Dim node As Object
Set mainnode = XMLFile.SelectNodes("//Elements")
For Each node In mainnode
For Each child In node.ChildNodes
Debug.Print child.BaseName
Dim kiddo As Object
For Each kiddo In child.ChildNodes
Debug.Print kiddo.BaseName
Next kiddo
Next child
Next node
End sub
Here is the sample XML. I need to get the attribute name num
from the XML.
<Elements>
<Details>
<Name>ABC</Name>
<Address>123ABC</Address>
<College>
<collname>safasf</collname>
<collnumber/>
</College>
</Details>
<Dept num="123">
<Deptname>IT</Deptname>
<ID>A123</ID>
</Dept>
</Elements>
Expected Result:
Elements
Details
Name
Address
College
collname
collnumber
Dept
num
Deptname
ID
Actual Result from above code:
Elements
Details
Name
Address
College
collname
Dept
Deptname
ID
The "num" attribute and <collnumber/>
tag is not fetched by my code. Could someone let me know how to fetch the attribute names along with the tag names from XML using VBA
Displaying XML structures including attributes via recursive function calls
My example code demonstrates a way to
[1]
assign the entire XML structure to a 2-dim array using XMLDOM methods and[2]
optionally write it back to a sheet.Amplifying hints:
I added these ► structured hints to offer more help than by displaying code only, as I remarked that many of these points lead to repeated questions by other users, too:
XML
structures you lose good view with increasing hierarchy depth of your node elements (type constant 1NODE_ELEMENT
), so I urgently recommend the use of ► recursive calls as used in this example code.NODE_TEXT
) being the first child of a name giving parent element - c.f. sections A. and B. in main functionlistChildNodes
. Your loops through child nodes would not distinguish between the mentioned types. Just study the comments in the cited function for details.<?xml version="1.0" encoding="utf-8"?>
, so that it can be actually identified as XML file.DisplayXML()
uses late binding instead of early bound reference to MS XML similar to your post, but uses the recommended MSXML2 version 6.0. It calls the main function via itsDocumentElement
<Elements>
(BTW a single node element) and a second argument referring to a predefined 2-dim arrayv
.XMLFILE
object to memory withSet XDoc = CreateObject("MSXML2.DOMDocument")
generally you are getting the older default Version (3.0), so in most cases it's preferrable to use explicitlySet XDoc = CreateObject("MSXML2.DOMDocument.6.0")
instead (including XPath automatically).Load
function to get aTrue
(file loaded successfully) orFalse
(load error) back, it is not necessary to set the file name into brackets ().//
in search strings would return any occurences at any level (c.f.XMLFile.SelectNodes("//Elements")
in your OP).Calling procedure
DisplayXML
Hint: It would sufficient to dimension the array 's row count only with an estimated number of items in the calling procedure (e.g. 1000), as the main function executes a
ReDim
(including a double transposition) automatically if needed. Nevertheless I added the exact items count here from the start via XPath/XMLDOM expressionXMLFile.SelectNodes("//*").Length
counting any item in the entire file.Structured results displayed in sheet
Hint: If you don't want the level indentation or enumerated Level hierarchy, you can easily adapt the main function
listChildNodes()
below.It is also possible to refer to a precise node element, e.g. via
This would list the indicated node set alone:
Recursive main function
listChildNodes()
Looping through childnode collections this function calls itself (i.e. the current node object) repeatedly ("recursively") and assigns the entire XML structure to a given 2-dim array (2nd argument). Furthermore it allows indendation and indicates the hierarchy levels. Note that the array in this example has to be 1-based.
Edit 20/8 2018
includes an automatic increase of array size if the items counteri
exceeds the current array's upper boundary (UBound(v)
, i.e. in its first dimension = items count). Technical note: As such aReDim
isn't possible in a minor (here 1st) dimension, an intermediate transposition changing 'rows' (dim 1) to 'columns' (dim 2) is necessary.'Helper function
getAtts()
This helper function called by the above function returns a string enumerating all attribute names and values of a given node similar to
XPath
notation; the code can be easily adapted to your needs.