Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在MSXML-VBA中获取XML元素的数组索引?_Xml_Vba_Excel - Fatal编程技术网

如何在MSXML-VBA中获取XML元素的数组索引?

如何在MSXML-VBA中获取XML元素的数组索引?,xml,vba,excel,Xml,Vba,Excel,我需要将XML文件转换为Excel。因此,我希望以名称-值对的形式检索XML,并对列进行唯一命名。是否有任何方法可以获取节点的XML数组索引?下面是示例XML,我想知道productInfo字段的索引 productInfo2_itemName我想你正在寻找一种神奇的药丸,它会自动为你转换一切,或者我根本不理解你的最终结果。然而,XML是一种标准,当您接收XML时,您通常会就接收内容和方式达成一致。也就是说,我不太明白像我这样读取根元素有什么问题(“/productInfoRequest”)如果

我需要将XML文件转换为Excel。因此,我希望以名称-值对的形式检索XML,并对列进行唯一命名。是否有任何方法可以获取节点的XML数组索引?下面是示例XML,我想知道productInfo字段的索引


productInfo2_itemName

我想你正在寻找一种神奇的药丸,它会自动为你转换一切,或者我根本不理解你的最终结果。然而,XML是一种标准,当您接收XML时,您通常会就接收内容和方式达成一致。也就是说,我不太明白像我这样读取根元素有什么问题
(“/productInfoRequest”)
如果此元素不是根元素,那么是什么? 为了解析方式,您需要解析,我们必须对读取XML的方式进行一些更改。查看更新的代码并运行它。这将按照您在las注释中描述的方式打印值并将值添加到字典中。 同样,您需要通过转到Tools->References添加对Microsoft XML V6.0库的引用。

这是代码

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 val As Variant
    Dim oXml As MSXML2.DOMDocument60
    Dim tempProduct As Variant
    Dim ItemName As String
    Dim ItemValue As String

    Set oXml = New MSXML2.DOMDocument60

     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> "

     oXml.LoadXML XML

    Set dic = CreateObject("Scripting.Dictionary")
    Set productdic = CreateObject("Scripting.Dictionary")
    Dim CurrVal
    Dim Cnt As Integer

    Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")

    With xmlDoc
        .async = False
        .validateOnParse = True
        .LoadXML CurrVal
    End With

    Set xmlNodes = oXml.SelectNodes("/productInfoRequest")
    Set productNodes = oXml.SelectNodes("/productInfoRequest/productInfo")

    Cnt = 0
    pcnt = 0

   For Each xNode In productNodes

        If xNode.HasChildNodes Then
             For Each cNode In xNode.ChildNodes
          ' by product loop the children and add once completed 
          ' add it to the dictionary
                  If cNode.BaseName = "itemName" Then
                     ItemName = cNode.BaseName
                     tempProduct = Array("product_Info" & CStr(pcnt) & cNode.BaseName)
                     tempProduct = Array(cNode.nodeTypedValue)
                     End If

                     If cNode.BaseName = "itemNo" Then
                     ItemValue = cNode.nodeTypedValue

                     End If

             Next

             Key = "productInfo" & CStr(pcnt) & "_" & ItemName
             val = ItemValue
             productdic.Add Key, val
             pcnt = pcnt + 1

       End If
    Next



    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
'    Debug.Print ("Key: " & KeyNo & " Value: " & dic(KeyNo))
'    Next

     For Each KeyNo In productdic.Keys
     Debug.Print ("Key: " & KeyNo & " Value: " & productdic(KeyNo))

    Next


End Sub
Sub-GenKeyValues()
Dim xmlDoc作为MSXML2.DOMDocument60
将xmlNodes设置为MSXML2.IXMLDOMNodeList
将xNode设置为MSXML2.IXMLDOMNode
作为MSXML2.IXMLDOMNode的Dim cNode
将ccNode设置为MSXML2.IXMLDOMNode
Dim KeyNo作为变型
Dim-val作为变体
Dim oXml作为MSXML2.DOMDocument60
作为变体的产品
将ItemName设置为字符串
将ItemValue设置为字符串
设置oXml=New MSXML2.DOMDocument60
XML=“假2016-11-02T15:49:57.337-05:00美国”+_
“1美元样本2”+_
“样本3样本4”+_
“样本”
oXml.LoadXML
设置dic=CreateObject(“Scripting.Dictionary”)
设置productdic=CreateObject(“Scripting.Dictionary”)
暗电流
作为整数的Dim Cnt
设置xmlDoc=CreateObject(“MSXML2.DOMDocument.6.0”)
使用xmlDoc
.async=False
.validateOnParse=True
.LoadXML CurrVal
以
设置xmlNodes=oXml.SelectNodes(“/productInfoRequest”)
设置productNodes=oXml.SelectNodes(“/productInfoRequest/productInfo”)
Cnt=0
pcnt=0
对于productNodes中的每个xNode
如果xNode.HasChildNodes,则
对于xNode.ChildNodes中的每个cNode
'按产品循环子项并在完成后添加
'将其添加到字典中
如果cNode.BaseName=“itemName”,则
ItemName=cNode.BaseName
tempProduct=Array(“产品信息”和CStr(pcnt)和cNode.BaseName)
tempProduct=数组(cNode.nodeTypedValue)
如果结束
如果cNode.BaseName=“itemNo”,则
ItemValue=cNode.nodeTypedValue
如果结束
下一个
Key=“productInfo”和CStr(pcnt)以及“u”和ItemName
val=项目值
productdic.addkey,val
pcnt=pcnt+1
如果结束
下一个
对于xmlNodes中的每个xNode
如果xNode.HasChildNodes,则
对于xNode.ChildNodes中的每个cNode
如果cNode.ChildNodes.Length>1,则
Cnt=Cnt+1
对于cNode.ChildNodes中的每个ccNode

Key=ccNode.ParentNode.BaseName+CStr(Cnt)+“”+ccNode.BaseName val=ccNode.nodeTypedValue 加钥匙,瓦尔 下一个 其他的 Key=cNode.BaseName val=cNode.nodeTypedValue 加钥匙,瓦尔 如果结束 下一个 如果结束 下一个 '对于dic.钥匙中的每个钥匙编号 'Debug.Print(“键:&KeyNo&”值:&dic(键号)) ”“接着呢 对于productdic.Keys中的每个KeyNo Debug.Print(“键:&KeyNo&”值:&productdic(键号)) 下一个 端接头

考虑一下,这是一种专用语言,旨在将XML文件转换为最终使用的格式,包括其他XML文件、HTML文件甚至文本文件。在这里,XSLT可以将您的结构转换为具有所需标题和数据行的CSV格式。MSXML可以运行XSLT1.0脚本,避免嵌套
for
if
逻辑和使用数组或字典

XSLT(另存为.xsl文件,在VBA中读取;注意:xsl脚本是XML文件)

CSV输出

当然,这是一个csv文件,而不是Excel工作簿。因此,请将内容保存或加载到工作簿中


嗨,米格尔,谢谢你的回复。我已经实施了一个解决方案。但我面临的唯一挑战是,我无法拥有唯一的键值对。我需要在分析子值时获取父项(产品信息)的索引,以便在创建时在excel中具有唯一的引用。我计划使用字典并加载值。键应该类似于productinfo1\u itemNo、productinfo2\u itemNo。在这里,我必须获得产品信息的数组位置,并将其附加到密钥以使其成为唯一的。好的,你能用你的解决方案更新帖子吗,我会帮助你得到你想要的。嗨,米格尔-我附上了一个只与我们的主题相关的示例代码片段。在这里,我使用了cnt和address使它以某种方式唯一,但我想知道xml元素数组的索引,以便它可以写入字典和excel,而无需重复键。Pl.注意,我可能无法使用XPATH,因为我使用相同的代码处理了不同格式的XML。@Vinoth上面提供的代码有几个问题,我已经解决了。如果要将键更改为数字-值对,则字典中的键是XML标记名中的值,这可以通过使用
c替换键轻松完成
foodoInfo0_Country
foodoInfo0_Currency
productInfo0_itemNo
productInfo0_itemName
productInfo1_itemNo
productInfo1_itemName
productInfo2_itemNo
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 val As Variant
    Dim oXml As MSXML2.DOMDocument60
    Dim tempProduct As Variant
    Dim ItemName As String
    Dim ItemValue As String

    Set oXml = New MSXML2.DOMDocument60

     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> "

     oXml.LoadXML XML

    Set dic = CreateObject("Scripting.Dictionary")
    Set productdic = CreateObject("Scripting.Dictionary")
    Dim CurrVal
    Dim Cnt As Integer

    Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")

    With xmlDoc
        .async = False
        .validateOnParse = True
        .LoadXML CurrVal
    End With

    Set xmlNodes = oXml.SelectNodes("/productInfoRequest")
    Set productNodes = oXml.SelectNodes("/productInfoRequest/productInfo")

    Cnt = 0
    pcnt = 0

   For Each xNode In productNodes

        If xNode.HasChildNodes Then
             For Each cNode In xNode.ChildNodes
          ' by product loop the children and add once completed 
          ' add it to the dictionary
                  If cNode.BaseName = "itemName" Then
                     ItemName = cNode.BaseName
                     tempProduct = Array("product_Info" & CStr(pcnt) & cNode.BaseName)
                     tempProduct = Array(cNode.nodeTypedValue)
                     End If

                     If cNode.BaseName = "itemNo" Then
                     ItemValue = cNode.nodeTypedValue

                     End If

             Next

             Key = "productInfo" & CStr(pcnt) & "_" & ItemName
             val = ItemValue
             productdic.Add Key, val
             pcnt = pcnt + 1

       End If
    Next



    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
'    Debug.Print ("Key: " & KeyNo & " Value: " & dic(KeyNo))
'    Next

     For Each KeyNo In productdic.Keys
     Debug.Print ("Key: " & KeyNo & " Value: " & productdic(KeyNo))

    Next


End Sub
<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>&#xa;</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>