You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将DOMDocument传递给子过程?XJustiz XML解析报错排查

问题详情

我有一批德国商事登记处的结构化XML数据(单文件对应单公司),符合XJustiz XML Schema(司法领域电子数据交换规范),当前数据同时存在v1和v3两个版本,Schema会定期更新结构、ID和标签名。

已编写独立代码处理不同版本的XML并导出数据到工作簿,现在要整合代码:主循环遍历指定目录的XML文件,加载为MSXML2.DOMDocument60实例,判断XJustiz版本后调用对应子过程。但子过程中访问DOM节点时始终触发Run-Time Error '91':对象变量或With块变量未设置,确认XML存在目标节点,且xmlDoc.Text能获取内容,但无法访问XML结构,无论传递DOM实例还是文件路径重新加载都无效,希望保留分模块的代码结构,寻求解决方案。

主过程代码

Sub Read_XML_Data()

 [...]

'########## MAIN LOOP START ##########
Do While Len(strFilePath) > 0

   Set xmlDoc = New MSXML2.DOMDocument60
   xmlDoc.async = False
   xmlDoc.Load (strFolder & strFilePath)
        
   'Checking the XJustiz version
   For Each xmlNode In xmlDoc.getElementsByTagName("*")
            
      If StrComp(xmlNode.Attributes(0).Name, "xjustizversion", vbTextCompare) = 0 Then
           
         Select Case Left(xmlNode.Attributes(0).Text, 1)
            
            'Found version 1 and execute corresponding subroutine
            Case 1
               Read_XJustiz_v1 xmlDoc
               Exit For
                    
            Case Else
               MsgBox (strFilePath & " verwendet XJustiz Version " & Left(xmlNode.Attributes(0).Text, 1))
               Exit For
           
         End Select
           
      End If
        
   Next
        
strFilePath = Dir
    
Loop
'########## MAIN LOOP END ##########

End Sub

子过程代码

Sub Read_XJustiz_v1(ByRef xmlDoc As DOMDocument60)

Dim strContent As String

   strContent = xmlDoc.Text
    
   'This line raises the Error No. 91: Object Variable or With Block Variable Not Set.
   If xmlDoc.getElementsByTagName("Beteiligter").Item(0).ChildNodes(1).ChildNodes(2).Text = "Gesellschaft mit beschränkter Haftung" Then
   [...]
   End If

End Sub
解决方案

1. 先确认XML加载是否成功

主过程中加载XML后,先检查加载状态,避免传递未成功加载的DOM:

Set xmlDoc = New MSXML2.DOMDocument60
xmlDoc.async = False
xmlDoc.validateOnParse = False '不需要验证Schema可关闭
If Not xmlDoc.Load(strFolder & strFilePath) Then
    MsgBox "文件加载失败: " & strFilePath & vbCrLf & xmlDoc.parseError.Reason
    GoTo NextFile '跳过该文件
End If

2. 处理命名空间问题(核心原因)

XJustiz XML通常带有命名空间,getElementsByTagName默认不识别命名空间,导致找不到节点。改用带命名空间的XPath查询:
在子过程中添加命名空间管理器:

Sub Read_XJustiz_v1(ByRef xmlDoc As MSXML2.DOMDocument60)
    Dim strContent As String
    Dim nsMgr As MSXML2.XMLNamespaceManager
    Dim beteiligterNodes As MSXML2.IXMLDOMNodeList
    Dim targetNode As MSXML2.IXMLDOMNode
    
    strContent = xmlDoc.Text
    
    '初始化命名空间管理器,替换为XML实际的命名空间URI
    Set nsMgr = New MSXML2.XMLNamespaceManager(xmlDoc.documentElement)
    nsMgr.AddNamespace "xj", "http://www.xjustiz.de/namespace/xjustiz/1.0" 'XJustiz v1的标准命名空间
    
    '用XPath查询目标节点
    Set beteiligterNodes = xmlDoc.selectNodes("//xj:Beteiligter", nsMgr)
    If beteiligterNodes.Length > 0 Then
        '按节点名查询子节点,避免依赖ChildNodes索引(易受空白节点影响)
        Set targetNode = beteiligterNodes(0).selectSingleNode("xj:Unternehmensform/xj:Bezeichnung", nsMgr) '替换为实际节点路径
        If Not targetNode Is Nothing Then
            If targetNode.Text = "Gesellschaft mit beschränkter Haftung" Then
                '执行后续逻辑
            End If
        End If
    End If
End Sub

3. 避免依赖ChildNodes索引

XML中的换行、空格会被解析为空白文本节点,导致ChildNodes(1)、ChildNodes(2)的索引与预期不符。改用selectSingleNode按节点名定位,确保精准找到目标节点。

4. 优化版本判断逻辑

原代码遍历所有节点并直接访问Attributes(0),若节点无属性会触发错误。优化为优先检查根节点属性,再遍历其他节点:

'Checking the XJustiz version
Dim versionAttr As MSXML2.IXMLDOMAttribute
'优先检查根节点的xjustizversion属性
Set versionAttr = xmlDoc.documentElement.Attributes.getNamedItem("xjustizversion")
If Not versionAttr Is Nothing Then
    Select Case Left(versionAttr.Value, 1)
        Case "1"
            Read_XJustiz_v1 xmlDoc
        Case "3"
            Read_XJustiz_v3 xmlDoc '对应v3子过程
        Case Else
            MsgBox strFilePath & " 使用XJustiz版本: " & versionAttr.Value
    End Select
Else
    '遍历所有节点查找属性
    For Each xmlNode In xmlDoc.getElementsByTagName("*")
        Set versionAttr = xmlNode.Attributes.getNamedItem("xjustizversion")
        If Not versionAttr Is Nothing Then
            Select Case Left(versionAttr.Value, 1)
                Case "1"
                    Read_XJustiz_v1 xmlDoc
                Case "3"
                    Read_XJustiz_v3 xmlDoc
                Case Else
                    MsgBox strFilePath & " 使用XJustiz版本: " & versionAttr.Value
            End Select
            Exit For
        End If
    Next
End If

5. 确认参数类型与库引用

  • 子过程参数需明确指定MSXML2.DOMDocument60,避免类型不匹配:
    Sub Read_XJustiz_v1(ByRef xmlDoc As MSXML2.DOMDocument60)
    
  • 确保VBA工程已引用Microsoft XML, v6.0(菜单:工具 -> 引用)

内容的提问来源于stack exchange,提问作者LuPi1801

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:40:56