【问题标题】:Handle NULL-values on XML-files处理 XML 文件上的 NULL 值
【发布时间】:2017-08-22 13:23:34
【问题描述】:

我正在尝试使用 VBA 中的 MSXML2.DOMDocument 对象将 XML 文件加载到 Excel 电子表格中。

我有以下方法:

Sub NEWTestXML()
    Dim xmlDoc As Object
    Dim xmlNodeList As Object
    Dim getFirstChild As Object

    Set xmlDoc = CreateObject("MSXML2.DOMDocument")
    xmlDoc.async = False: xmlDoc.validateOnParse = False
    xmlDoc.Load ("H:\Anders\BankStatements\LoadXML\CAMT\20170818_070648_DANSKEBANK_DECS_20170818070531_3.xml")
    If xmlDoc.parseError.ErrorCode <> 0 Then
        MsgBox "Error was " + xmlDoc.parseError.reason
    End If

    'Get Document Elements
    Set xmlNodeList = xmlDoc.DocumentElement

    'Get first child ( same as ChildNodes(0) )
    Set getFirstChild = xmlNodeList.FirstChild
    'Print first child XML
    Debug.Print getFirstChild.XML
    'Print first child Text
    Debug.Print getFirstChild.Text

    Set getFirstChild = Nothing
    Set xmlNodeList = Nothing
    Set xmlDoc = Nothing
End Sub

取自通过 Google 找到的示例。

我从银行收到的文件包含一个 NULL 字符,这使我无法使用上述方法加载文件。

删除 NULL 值解决了我遇到的问题。

它们看起来像这样:

我一直在尝试使用 Access-databases 和各种方法加载这些文件,但每次这些 NULL 值都让我变得更好。

我的问题是:

是否有任何编程方法可以删除这些 NULL 值,在 Notepad++ 中显示? MSXML2 或类似的参数?

我之前创建了一个复制 XML 文件并删除最后一行的方法,但我想在当前解决方案中避免这种情况。

【问题讨论】:

  • 空字符由“\x00”表示。以文本模式打开文件并将所有出现的 \x00 替换为空字符串。然后通过 XML 解析器加载它。
  • @EylM 没那么简单。正确“以文本模式打开文件”需要事先了解文件编码。
  • 它是“utf-8” - 查看示例。
  • 嗨,EyIM。感谢您的建议,但由于我们每天都有数百个文件,因此在 notepad++ 中手动打开它们是不可行的。据我所知,即使您有可能一次编辑多个文件。

标签: xml vba xpath null notepad++


【解决方案1】:

如果有机会,请修复写入那些错误文件的进程。

NULL 字节在 XML 文件中是非法的,它也不会自然出现在 UTF-8 编码的文本文件中,这意味着生成这些文件的东西......

  • ...要么没有正确的 UTF-8 或 XML 概念,要么
  • 无缘无故将 NULL 字节写入文件

这两件事都很糟糕,应该在生产者中修复,而不是在这些文件的消费者中修复。仔细检查为您提供这些文件的过程,并找出问题所在。


如果这不是一个选项,仍然可以使用辅助函数将文件作为纯文本加载,如下所示:

Function LoadFile(path As String, charset As String) As String
    Dim inputStream As New ADODB.Stream

    inputStream.Type = adTypeText
    inputStream.charset = charset
    inputStream.Open
    inputStream.LoadFromFile path

    LoadFile = inputStream.ReadText
End Function

这利用了ReadText()(至少对于 UTF-8 而言)在找到的第一个 NULL 字节处停止这一事实,因此在您的情况下,它将读取整个文件,不包括最后一个字节。

然后使用LoadXML() 将该字符串解析为 XML 文档:

Sub NEWTestXML()
    Dim xmlDoc As New MSXML2.DOMDocument
    Dim xmlNodeList As MSXML2.IXMLDOMNodeList
    Dim docElem As MSXML2.IXMLDOMElement
    Dim filePath As String

    xmlDoc.async = False
    xmlDoc.validateOnParse = False

    filePath = "H:\Anders\BankStatements\LoadXML\CAMT\20170818_070648_DANSKEBANK_DECS_20170818070531_3.xml"
    xmlDoc.LoadXML LoadFile(filePath, "UTF-8")

    If xmlDoc.parseError.ErrorCode <> 0 Then
        Debug.Print "Error: " + xmlDoc.parseError.reason
        Exit Sub
    End If

    Set docElem = xmlDoc.DocumentElement

    Debug.Print docElem.FirstChild.XML
    Debug.Print docElem.FirstChild.Text
End Sub

这种方法有一个缺点: 为了正确读取字符串,您需要预先知道文件编码,这正是 XML 旨在避免的事情。

换句话说,如果某个 XML 文件不是 UTF-8 编码的,而是使用其他一些完全合法的编码,那么上述方法将失败,因为它对文件编码做出了盲目的假设。当然,这不是您想要长期使用的东西。

以上要求您添加两个对您的 VBA 项目的引用

  • “Microsoft ActiveX 数据对象”库的最新版本
  • “Microsoft XML”库的最新版本

【讨论】:

  • 嗨 Tomalak 感谢您提供非常详尽、彻底和有用的答案。
  • 不幸的是,我无法控制文件的生成,正如您所建议的那样,这将是解决问题的正确和最佳方法。 NULL 字符始终位于文件末尾。因此设法创建了一个方法来打开 XML 文件并删除“”之后的所有内容。除此之外,我可以使用 LoadXML 方法。
  • 这也行。它仍然做了一个盲目的假设,即你的文件总是以“”结尾,但它可能对你的情况来说已经足够了。人必须在某个时候妥协。
  • 谨防在未指定编码的情况下将 XML 文件作为文本打开 - 这就是我在上面所说的重点。这很容易搞砸。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-25
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
相关资源
最近更新 更多