我正在将 VBA Access 应用程序从 Win7 移植到 Win11,我认为应该有一种方法可以做得更优雅。我必须阅读这个 .xml 文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Document
xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08 camt.053.001.08.xsd"
xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BkToCstmrStmt>
<GrpHdr>
<MsgId>MSG-C053-231229020607-01</MsgId>
<CreDtTm>2023-12-29T14:06:07.386+01:00</CreDtTm>
<AddtlInf>RECONSTRUCTION</AddtlInf>
</GrpHdr>
<Stmt>
<Id>STM-C053-231229020607-01</Id>
<ElctrncSeqNb>999999</ElctrncSeqNb>
<CreDtTm>2023-12-29T14:06:07.386+01:00</CreDtTm>
<FrToDt>
<FrDtTm>2023-11-29T00:00:00.000+01:00</FrDtTm>
<ToDtTm>2023-12-28T23:59:59.999+01:00</ToDtTm>
</FrToDt>
<CpyDplctInd>DUPL</CpyDplctInd>
<Acct>
<Id>
<IBAN>CHxxxxxxxxxxxxxxxxx</IBAN>
</Id>
<Ccy>CHF</Ccy>
<Ownr>
<Nm>Entity</Nm>
</Ownr>
<Svcr>
<FinInstnId>
<Nm>Name of Bank</Nm>
</FinInstnId>
</Svcr>
</Acct>
<Bal>
<Shortened>
</Shortened>
</Bal>
<Bal>
<Shortened>
</Shortened>
</Bal>
<Ntry>
<Shortened>
</Shortened>
</Ntry>
</Stmt>
</BkToCstmrStmt>
</Document>
在Win7中使用\Windows\system32\msxml6.dll,这段代码做得很完美:
Sub ReadCamt053(strDPFE As String)
Dim bankDownload As MSXML2.DOMDocument
Set bankDownload = New MSXML2.DOMDocument
bankDownload.validateOnParse = True
bankDownload.Load strDPFE
Dim groupHeader As IXMLDOMNode
For Each groupHeader In bankDownload.selectNodes("Document/BkToCstmrStmt/GrpHdr")
Debug.Print "Erzeugungsdatum(CreDtTm)", groupHeader.selectSingleNode("CreDtTm").Text
Next groupHeader
Dim accountStatement As IXMLDOMNode
For Each accountStatement In bankDownload.selectNodes("Document/BkToCstmrStmt/Stmt")
gIBAN = accountStatement.selectSingleNode("Acct/Id/IBAN").Text
gSequenzNr = accountStatement.selectSingleNode("ElctrncSeqNb").Text
ReadStatementEntries accountStatement.selectNodes("Ntry")
Next accountStatement
End Sub
对于Win11 \Windows\SysWOW64\msxml6.dll 的移植,选择了XML,这需要使用DOMDocument60 而不是DOMDocument。使用 Google,我从 MS 找到了 this,并假设我必须添加一个命名空间才能读取 XML。我这样做了,但我无法找到一种优雅的方式来添加 groupHeader.selectSingleNode("CreDtTm").Text 的名称空间 - groupHeader.selectSingleNode("/ns:CreDtTm").Text 导致错误 91,使用
groupHeader.selectSingleNode("/bk:Document/bk:BkToCstmrStmt/bk:GrpHdr/bk:CreDtTm").Text
有效,但似乎很难阅读......
Sub ReadCamt053(strDPFE As String)
Dim bankDownload As MSXML2.DOMDocument60
Set bankDownload = New MSXML2.DOMDocument60
bankDownload.validateOnParse = True
bankDownload.SetProperty "SelectionNamespaces", "xmlns:ns='urn:iso:std:iso:20022:tech:xsd:camt.053.001.08'"
bankDownload.Load strDPFE
Dim groupHeader As IXMLDOMNode
For Each groupHeader In bankDownload.selectNodes("/ns:Document/ns:BkToCstmrStmt/ns:GrpHdr")
Debug.Print "Erzeugungsdatum(CreDtTm)", groupHeader.selectSingleNode("CreDtTm").Text '<---
Next groupHeader
Dim accountStatement As IXMLDOMNode
For Each accountStatement In bankDownload.selectNodes("Document/BkToCstmrStmt/Stmt")
gIBAN = accountStatement.selectSingleNode("Acct/Id/IBAN").Text
gSequenzNr = accountStatement.selectSingleNode("ElctrncSeqNb").Text
ReadStatementEntries accountStatement.selectNodes("Ntry")
Next accountStatement
End Sub
我对 .XML 的了解非常有限(尝试错误)。所以这是我的两个问题:
有没有比 groupHeader.selectSingleNode("/bk:Document/bk:BkToCstmrStmt/bk:GrpHdr/bk:CreDtTm") 更好的方法
有关这个名称空间的整个内容看起来相当笨拙。有没有办法在不不断重复名称空间的情况下做到这一点 - 我确实只有这个单一的名称空间,所以这似乎是一个巨大的杀伤力......旧的东西完成了工作,看起来好多了......
1- 如果添加命名空间,则修改代码如下:
For Each groupHeader In bankDownload.selectNodes("ns:Document/ns:BkToCstmrStmt/ns:GrpHdr")
Debug.Print "Erzeugungsdatum(CreDtTm)", groupHeader.selectSingleNode("ns:CreDtTm").Text
Next groupHeader
For Each accountStatement In bankDownload.selectNodes("ns:Document/ns:BkToCstmrStmt/ns:Stmt")
gIBAN = accountStatement.selectSingleNode("ns:Acct/ns:Id/ns:IBAN").Text
gSequenzNr = accountStatement.selectSingleNode("ns:ElctrncSeqNb").Text
ReadStatementEntries accountStatement.selectNodes("ns:Ntry")
Next accountStatement
或
2- 从文档中删除命名空间,使
<Document xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08 camt.053.001.08.xsd" xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
变为 <Document>
并像以前一样使用原始代码:
Const s1 = "xsi:schemaLocation=""urn:iso:std:iso:20022:tech:xsd:camt.053.001.08 camt.053.001.08.xsd"""
Const s2 = "xmlns=""urn:iso:std:iso:20022:tech:xsd:camt.053.001.08"""
Const s3 = "xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"""
Dim bankDownload As New MSXML2.DOMDocument60
bankDownload.validateOnParse = False
bankDownload.Load Path_To_XML_File
Dim xml As String
xml = bankDownload.xml
xml = Replace(xml, s1, "")
xml = Replace(xml, s2, "")
xml = Replace(xml, s3, "")
bankDownload.loadXML xml
Dim groupHeader As IXMLDOMNode
For Each groupHeader In bankDownload.selectNodes("Document/BkToCstmrStmt/GrpHdr")
Debug.Print "Erzeugungsdatum(CreDtTm)", groupHeader.selectSingleNode("CreDtTm").Text
Next groupHeader
Dim accountStatement As IXMLDOMNode
For Each accountStatement In bankDownload.selectNodes("Document/BkToCstmrStmt/Stmt")
gIBAN = accountStatement.selectSingleNode("Acct/Id/IBAN").Text
gSequenzNr = accountStatement.selectSingleNode("ElctrncSeqNb").Text
ReadStatementEntries accountStatement.selectNodes("Ntry")
Next accountStatement