我需要将 XML 文件转换为 Excel。所以我想检索 XML 作为名称值对并唯一地命名列。有什么方法可以获取节点的 XML 数组索引吗?下面是我想知道 productInfo 字段索引的示例 XML。
<productInfoRequest>
<CheckIn>false</CheckIn>
<timeStamp>2016-11-02T15:49:57.337-05:00</timeStamp>
<foodoInfo>
<Country>USA</Country>
<Currency>USD</Currency>
</foodoInfo>
<productInfo>
<itemNo>1</itemNo>
<itemName>Sample</itemName>
</productInfo>
<productInfo>
<itemNo>2</itemNo>
<itemName>Sample</itemName>
</productInfo>
<productInfo>
<itemNo>3</itemNo>
<itemName>Sample</itemName>
</productInfo>
<productInfo>
<itemNo>4</itemNo>
<itemName>Sample</itemName>
</productInfo>
</productInfoRequest>
Desired Output
请注意,这只是我给出的示例请求 xml。任何给定的 XML 都应转换为唯一的键值对键并加载到 excel 中
示例代码片段:
Sub GenKeyValues()
Dim xmlDoc As MSXML2.DOMDocument60
Dim xmlNodes As MSXML2.IXMLDOMNodeList
Dim xNode As MSXML2.IXMLDOMNode
Dim cNode As MSXML2.IXMLDOMNode
Dim ccNode As MSXML2.IXMLDOMNode
Dim KeyNo As Variant
Dim dic
Set dic = CreateObject("Scripting.Dictionary")
Dim CurrVal
Dim Cnt As Integer
CurrVal = <<<<<Im reading the XML from the file to a string from another method>>>>>
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
With xmlDoc
.async = False
.validateOnParse = True
.LoadXML CurrVal
End With
Set xmlNodes = xmlDoc.ChildNodes
cnt = 0
For Each xNode In xmlNodes
If xNode.HasChildNodes Then
For Each cNode In xNode.ChildNodes
If cNode.ChildNodes.Length > 1 Then
cnt = cnt + 1
For Each ccNode In cNode.ChildNodes
Key = ccNode.ParentNode.BaseName + CStr(cnt) + "_" + ccNode.BaseName
Val = ccNode.nodeTypedValue
dic.Add Key, Val
Next
Else
Key = cNode.BaseName
Val = cNode.nodeTypedValue
dic.Add Key, Val
End If
Next
End If
Next
For Each KeyNo In dic.Keys
MsgBox ("Key: " & KeyNo & " Value: " & dic(KeyNo))
Next
End Sub
我已检索以下 key :
foodoInfo0_Country
foodoInfo0_Currency
productInfo0_itemNo
productInfo0_itemName
productInfo1_itemNo
productInfo1_itemName
productInfo2_itemNo
productInfo2_itemName
最佳答案
考虑XSLT ,一种专用语言,旨在将 XML 文件转换为最终用途格式,包括其他 XML 文件、HTML 文件,甚至文本文件。在这里,XSLT 可以将您的结构转换为带有所需标题和数据行的 CSV 格式。 MSXML 可以运行 XSLT 1.0 脚本,避免嵌套 for
和 if
逻辑和数组或字典的使用。
XSLT (另存为 .xsl 文件以在 VBA 中读取;注意:XSL 脚本是 XML 文件)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/productInfoRequest">
<xsl:call-template name="rows">
<xsl:with-param name="data" select="foodoInfo|productInfo"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="rows">
<xsl:param name="data"/>
<!-- HEADERS -->
<xsl:for-each select="$data">
<xsl:value-of select="concat(name(), position(), '_', name(*[1]))"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="concat(name(), position(), '_', name(*[2]))"/>
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
<!-- DATA -->
<xsl:for-each select="$data">
<xsl:value-of select="concat(node()[1], ',', node()[2])"/>
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
VBA
Public Sub RunXSLTtoCSV()
Dim xmlDoc As New MSXML2.DOMDocument60, xslDoc As New MSXML2.DOMDocument60
Dim txtOutput As String, csvfile As String
' LOAD XML AND XSL
xmlDoc.LoadXML CurrVal
xmlDoc.async = False
xslDoc.Load "C:\Path\To\XSLScript.xsl"
xslDoc.async = False
' TRANSFORM TO TEXT
txtOutput = xmlDoc.transformNode(xslDoc)
' SAVE TO CSV
csvfile = "C:\Path\To\CSV.csv"
Open csvfile For Output As #1
Print #1, txtOutput
Close #1
Set xslDoc = Nothing
Set xmlDoc = Nothing
End Sub
CSV 输出
当然这是一个 csv 文件,而不是 Excel 工作簿。因此,将内容保存或加载到工作簿中。
关于xml - 如何在 MSXML - VBA 中获取 XML 元素的数组索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43192810/