【问题标题】:getElementsByTagName returning "Wrong number of arguments or invalid property assignment" errorgetElementsByTagName 返回“参数数量错误或属性分配无效”错误
【发布时间】:2021-12-29 11:17:13
【问题描述】:

我正在使用供应商提供的 API,当我调用它时会返回此 XML。

<RESPONSE>
    <VALID>true</VALID>
    <MESSAGE></MESSAGE>
    <DATA>
        <WORK>
            <ROW type="object" class="empty">
                <brief_desc>Check plate</brief_desc>
                <compid>1354</compid>
                <comp_desc>Spitfire #2</comp_desc>
                <initials></initials>
                <sch_date>2019-10-01</sch_date>
                <wo>43351</wo>
                <workstatus>O</workstatus>
                <work_desc>Check plate for flatness</work_desc>
            </ROW>
            <ROW type="object" class="empty">
                <brief_desc>Check wheel</brief_desc>
                <compid>1354</compid>
                <comp_desc>Spitfire #1</comp_desc>
                <initials></initials>
                <sch_date>2019-10-08</sch_date>
                <wo>43685</wo>
                <workstatus>O</workstatus>
                <work_desc>Check wheel for roundness</work_desc>
            </ROW>
        </WORK>
    </DATA>
</RESPONSE>

我从另一个供应商提供的 HMI 软件中调用它,它只支持 VBscript。我可以使用 Microsoft.XMLDOM 对象获得这样的单个值:

xmlDoc.documentElement.selectSingleNode("//VALID").text

但是,当我尝试获取“WORK”节点的集合时,就像这样......

objNodeList = xmlDoc.getElementsByTagName("DATA")

...我收到一条错误消息,指出“参数数量错误或属性分配无效”。 “DATA”元素全部大写,所以我想我的名字是正确的。我对此进行了相当多的研究,但似乎找不到有完全相同问题的人。我将不胜感激任何人可能有的任何建议。谢谢!

根据回复此帖子的人的要求,编辑、添加完整代码:

Function EmaintTest

    Dim objRequest
    Dim strUrl 
    Dim strResponse 
    Dim body 
    Dim strResponseHeaders 
    Dim allResponseHeader 
    Dim xmlDoc 
    
    Set objRequest = CreateObject("MSXML2.XMLHTTP")
    strUrl = "https://somewebsite.com/wc.dll?x3~api~&q=GetAnyData"
    
    'Set body value as required by API.
    body = "{""table"":""WORK"",""columns"":""WO,COMPID,COMP_DESC,WORKSTATUS,BRIEF_DESC,SCH_DATE,WORK_DESC,INITIALS"",""pageNumber"":1,""pageSize"":1000,""filter"":{""logic"":""and"",""filters"":[{""field"":""wo_type"",""operator"":""eq"",""value"":""PM""},{""field"":""COMPID"",""operator"":""eq"",""value"":""1354""},{""field"":""WORKSTATUS"",""operator"":""eq"",""value"":""O""}]},""sortBy"":[{""field"":""SCH_DATE"",""dir"":""asc""}]}"             
                
    With objRequest
        .Open "POST", strUrl, False
        .SetRequestHeader "Cache-Control", "no-cache"
        .SetRequestHeader "Content-Type", "text/plain"
        .SetRequestHeader "Accept", "application/xml"
        .SetRequestHeader "Accept-Encoding", "gzip, deflate, br"
        .SetRequestHeader "Connection", "keep-alive"
        .Send body
        strResponseHeaders = .StatusText
        strResponse = .ResponseText
        allResponseHeader = .GetAllResponseHeaders
    End With
        
    'Load the XML
    Set xmlDoc = CreateObject("Microsoft.XMLDOM")
    xmlDoc.async = False 
    xmlDoc.loadXML(strResponse)

    'Assign variables using the values returned from the API 
    $Trace (xmlDoc.documentElement.selectSingleNode("//VALID").text ) 'This works, returns "True" value.

    Dim xmlNodes
    Dim xmlNode  

    Set xmlNodes = xmlDoc.documentElement.selectNodes("DATA/WORK")
    
    $Trace  ("Using selectNodes...")
    
    For Each xmlNode in xmlNodes
        $Trace (xmlNode.text)
    Next
    
    $Trace  ("Using getElementsByTagName...")

    Set xmlNodes = xmlDoc.getElementsByTagName("DATA/WORK")

    For Each xmlNode In xmlNodes
        $Trace  (xmlNode.text)
    Next

End Function

【问题讨论】:

  • 请尝试以下 XPath 表达式:/RESPONSE/DATA
  • Yitzhak - 感谢您的回复。当我尝试这样做时,我收到了以下错误消息:“意外的令牌'/'。”可能是我使用的 VBScript 版本没有这个功能(?)。如果您想到其他我可以尝试的方法,请告诉我。
  • 提供的 XML 不是格式正确的 XML。请编辑您的问题,并提供一个真实的 XML。
  • 另外,请在问题中添加代码,使其成为最小可重现示例。
  • Yitzhak - 我编辑了 XML 示例以包含最终的“RESPONSE”标签(出于某种原因,SO 编辑器正在删除它)。我的代码有点大,与这个问题无关。我将尝试删除多余的代码并用一个可重现的示例回发。感谢您的回复。

标签: xml xmldom


【解决方案1】:

问题似乎与您尚未共享的代码有关。以下代码适用于您的 XML 文件。请注意,您可以选择使用 selectNodesgetElementsByTagName

Set xmlDoc =  CreateObject("Microsoft.XMLDOM")
xmlDoc.Load ".\Test.xml"

WScript.echo "Using selectNodes..."

Set xmlNodes = xmlDoc.documentElement.selectNodes("DATA/WORK")

For Each xmlNode in xmlNodes
  WScript.echo xmlNode.text
Next

WScript.echo "Using getElementsByTagName..."

Set xmlNodes = xmlDoc.getElementsByTagName("DATA/WORK")

For Each xmlNode in xmlNodes
  WScript.echo xmlNode.text
Next

下面是遍历所有节点的方法:

Set xmlDoc =  CreateObject("Microsoft.XMLDOM")
xmlDoc.Load ".\Test.xml"

Set xmlNodes = xmlDoc.selectNodes("//*")    
For i = 0 to xmlNodes.length - 1
    WScript.Echo xmlNodes(i).nodeName & ": " & xmlNodes(i).text
Next

【讨论】:

  • LesFerch - 感谢您的回复。你是对的,你的代码有效。我已经编辑了我的原始帖子以包含完整的代码,包括您的示例。但是,For Each 循环仅返回一个值,其中包含所有数据。例如:“检查板 1354 Spitfire #2 2019-10-01 43351 O 检查板的平整度 检查轮 1354 Spitfire #1 2019-10-08 43685 O 检查板的圆度”。如何让它为每个节点返回单独的值?
  • 我用代码扩展了答案以遍历所有节点。如果这就是您要查找的内容,那么这将是以下内容的副本:stackoverflow.com/q/1908526/15764378
  • LesFerch - 您遍历所有节点的方法运行良好,因此我将其标记为答案。此外,您发布的其他参考资料也很有帮助。非常感谢您的回复!
【解决方案2】:

我建议使用不同的方法,即selectNodes()

objNodeList = xmlDoc.selectNodes("/RESPONSE/DATA")

objNodeList = xmlDoc.selectNodes("/RESPONSE/DATA/WORK/ROW")

【讨论】:

  • 不幸的是,这些其他方法会产生与 getElementsByTagName 方法相同的“参数数量错误或属性分配无效”错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多