【问题标题】:"Object Variable Not Set" on IXMLDOMNode of MsXml-DOMDocument procedureMsXml-DOMDocument 过程的 IXMLDOMNode 上的“未设置对象变量”
【发布时间】:2020-07-13 23:11:31
【问题描述】:

所以我有一个非常大的 XML 文件 (40MB),我必须反复搜索。我受过关于使用 XPath 使用 DOMDocument 的好处的教育,我认为我做对了,但我得到了 Obj Var Not Set 的废话。

这是初始加载...我认为它的加载是因为它会延迟 40mb 文件的适当时间长度并且不返回错误。

Dim someElement As IXMLDOMNode
Dim xmlDoc As Object
Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0")

'<-thats a valid file name lookup
xmlDoc.Load DLookup("gsgtver", "Eramdat", "EramID = 1") 

所以这就是它变得冒险的地方。我需要一个 IXMLDOMNode 来读取 parced xmlDoc 对象。我检查了 MsXml 6.0 参考库,当我变暗时我得到了 var 类型(你知道,为我们新手填写的类型列表)。 在我设置了 IXMLDOMNode 后,当我尝试分配时,我得到了方法列表(如“.text”),但我正在解决这个错误.....可能是一个 bum xpath 字符串(虽然我几乎逐字从 xpath 教程中偷来的)。

sNodeName = "/Fix_Records/FixRecord/FixID[1]/Latitude"
Set someElement = xmlDoc.SelectSingleNode(sNodeName)

'yes, I dimmed xBuffer as a string up above
sBuffer = someElement.text 

顺便说一句,我真的很想做一个“FixID = 'mystring'”之类的事情,但我正在做元素 1 只是为了让它工作。 这是 xml 文件的顶部:

<Fix_Records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="Fix.xsd"> 
 <!-- ******************************************************** -->
 <!-- Local SITE ID        : ZAB                               -->
 <!-- Local Release Version: a082a210                          -->
 <!-- NASD/NADR Version    : z084b210                          -->
 <!-- Date                 : 02-03-2011 19:02:56               -->
 <!-- ******************************************************** -->

    <FixRecord>
      <FixId>00BTR</FixId>
      <IcaoCode>K7</IcaoCode>
      <FixType>WAYPOINT</FixType>
      <FixName>BTR055100</FixName>
      <FixinUs>true</FixinUs>
      <IsNational>true</IsNational>
      <HighPowerVor>false</HighPowerVor>
      <DPositionMapData>false</DPositionMapData>
      <Latitude>31170205N</Latitude>
      <Longitude>089353453W</Longitude>
      <AngularCorr>-0.010472</AngularCorr>
      <XSpherical>0.006082693951808</XSpherical>
      <YSpherical>-0.85612436871425</YSpherical>
      <ZSpherical>0.516734038096893</ZSpherical>
    </FixRecord>
    <FixRecord>
      <FixId>00N10</FixId>
      <IcaoCode>MM</IcaoCode>

谢谢......你们这些聪明的人摇滚。

【问题讨论】:

    标签: xml ms-access xpath vba


    【解决方案1】:

    您的 XPath 错误。 "/Fix_Records/FixRecord/FixID[1]/Latitude" 表示您正在寻找FixRecord 元素的第一个FixID 子元素的Latitude 子元素。

    但是:

    • 有很多FixRecord元素,
    • 对于任何给定的FixRecord,只有一个FixId 子元素(无需指定[1]),并且
    • 最重要的是,FixId 没有Latitude 子元素!因此,您正在寻找不存在的东西,这就是导致错误的原因。
      • 还要注意@James Walford 指出的区分大小写。 FixId 不是 FixID

    我想你想要的是:"/Fix_Records/FixRecord[1]/Latitude"

    当你准备好进入下一个级别时,试试这个:

    "/Fix_Records/FixRecord[FixId='mystring']/Latitude".

    如果这不起作用,可能会有一些命名空间怪异...尝试在 Xpath 中的每个节点规范之前添加 xsi:

    "/xsi:Fix_Records/xsi:FixRecord[1]/xsi:Latitude"
    "/xsi:Fix_Records/xsi:FixRecord[xsi:FixId='mystring']/xsi:Latitude"
    

    振作起来,你最终会到达那里的!!

    【讨论】:

    • JFC,你是我的英雄。我不需要 xsi 部分...在您尝试的第一次“粘贴”时就搞定了。
    【解决方案2】:

    您有一个区分大小写的问题 - 您正在寻找 FixID,实际上您已经获得了 FixId。 当您尝试访问其文本时,您会抛出异常,因为您没有实际对象。

    编辑:正如 Jean-François Corbett 所指出的,您的 XPath 也是错误的。这是解决这两个问题的更新 Xpath:

    "/Fix_Records/FixRecord[FixId='Id you want']/Latitude"
    

    您可能还想测试是否有要访问的节点,请参阅下面的答案以获取一些提示。

    【讨论】:

    • 嗯....我猜你实际上是第一个赢家。我以为我粘贴了你的行,但它没有用,但它实际上与 JFC 的一样......而且我现在已经阅读了所有的 cmets。所以谢谢,你得到了答案。我希望我做对了这件事。
    • 嗯,有两个答案解决了一半的问题,每个都更新以解决其余问题,尽管它们几乎相同,但您可以选择自己喜欢的答案。我本着分享的精神投票支持 JFC 的回答 :-)
    • 哦,看了下面的测试代码,没有检查你的节点是否在里面返回。 childnode.length 测试仍将引发异常。尝试 'if not myNode Is Nothing'(进行处理)否则(糟糕,出错了)。
    • 谢谢詹姆斯.....是的,我有点担心谁先回答了什么......试图成为joo-dishes。并感谢错误提示...我回到这里希望子节点异常能够得到解决,因为我有一段时间将它困在我的意大利面条中。
    • 这不是一个真正的问题,StackOverflow 在这类事情上通常相当悠闲。优先级通常优先于第一个正确答案,但具有更多/更好细节的稍后答案也是一个公平的选择。您可以随时投票赞成任何有帮助的答案。很高兴您接受答案,但新用户并不总是记得! Jazaddict 先生,度过一个 Miles and Trane 周末。
    【解决方案3】:

    一旦加载了 XML,仍然有可能出现解析错误。此代码可以帮助您找到问题所在。相应地更改它以适应您的环境。

    错误编号 (6666) 显然是个玩笑,您的应用程序必须有正确的错误编号。

    编辑:另外,尝试在 XML 验证器中解析您的 XML(或至少部分),例如 http://www.validome.org/xml/validate/

    Public Sub readXMLDoc()
    
        Dim objXML As MSXML2.DOMDocument
        Dim lookupNode As MSXML2.IXMLDOMNode
        Dim vOut As Variant
        Dim sNodeName As String
        Dim sParseError As String
    
    
        On Error GoTo ProcError
    
        Set objXML = New MSXML2.DOMDocument
    
        objXML.async = False
        objXML.LoadXML "c:\XMLSample.xml"
    
        If objXML Is Nothing Then Err.Raise 6666, , "Error while opening the XML file"
    
        sParseError = objXML.parseError.reason
    
        If Len(sParseError) > 0 Then Err.Raise 6666, , "Error while parsing the XML file: " & sParseError
    
        sNodeName = "/Fix_Records/FixRecord/FixID[1]/Latitude"
    
        Set lookupNode = objXML.SelectSingleNode(sNodeName)
    
        If lookupNode.ChildNodes.Length > 0 Then
    
            'Do your handling
    
        End If
    
    ProcExit:
    
        Exit Sub
    
    ProcError:
    
        Debug.Assert False
        Debug.Print Err.Description
        Resume ProcExit
    
    End Sub
    

    【讨论】:

    • 谢谢大家...我得好好研究一下这些东西....直到星期一才结束。
    • 感谢您的测试代码...我会保留它以备不时之需“下次”我无法完成这项工作。
    猜你喜欢
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多