【问题标题】:XML parsing in Excel VBA doesn't find my nodeExcel VBA 中的 XML 解析找不到我的节点
【发布时间】:2023-03-14 03:46:01
【问题描述】:

我有一个要解析的 XML 文件。该文件包含有关水肺潜水的信息。它的结构非常简单:

<Dive xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Suunto.Diving.Dal">
   <Algorithm>1</Algorithm>
   <AltitudeMode>0</AltitudeMode>
   <AscentTime i:nil="true"/>
   <AvgDepth>9.36</AvgDepth>
   <Boat i:nil="true"/>
   <BottomTemperature>23</BottomTemperature>
   <BottomTime i:nil="true"/>
   <CnsEnd>1</CnsEnd>
   <CnsStart>0</CnsStart>
   <CylinderVolume>12</CylinderVolume>
   <CylinderWorkPressure>232000</CylinderWorkPressure>
   <Deleted i:nil="true"/>
   <DeltaPressure i:nil="true"/>
   <DesaturationTime i:nil="true"/>
   <DiveMixtures>
      <DiveMixture>
         <DiveGasChanges/>
         <EndPressure>47300</EndPressure> 
         <Helium>0</Helium>
         <Name i:nil="true"/>
         <Oxygen>21</Oxygen>
         <PO2>0</PO2>
         <Size>0</Size>
         <StartPressure>208100</StartPressure>
         <TransmitterId i:nil="true"/>
         <Type>4</Type>
   </DiveMixture>
</DiveMixtures>
<DiveNumberInSerie>2</DiveNumberInSerie>
<DiveSamples>
   <Dive.Sample>
      <AveragedTemperature>26</AveragedTemperature>
      <Ceiling i:nil="true"/>
      <Depth>1.23</Depth>
      <GasTime i:nil="true"/>
      <Heading i:nil="true"/>
      <Pressure>208100</Pressure>
      <SacRate>27.0936737</SacRate>
      <Temperature>26</Temperature>
      <Time>0</Time>
   </Dive.Sample>
   <Dive.Sample>
      <AveragedTemperature>26</AveragedTemperature>
      <Ceiling i:nil="true"/>
      <Depth>3.29</Depth>
      <GasTime i:nil="true"/>
      <Heading i:nil="true"/>
      <Pressure>206800</Pressure>
      <SacRate>28.29174</SacRate>
      <Temperature>26</Temperature>
      <Time>20</Time>
   </Dive.Sample>
</DiveSamples>
<DiveTags/>
<DiveTime i:nil="true"/>
<DivingDaysInRow i:nil="true"/>
<Duration>3595</Duration>
<EndPressure>47300</EndPressure>
<EndTemperature>25</EndTemperature>
</Dive>

现在我想提取持续时间、平均深度等信息。此外,我需要将每个“Dive.Sample”容器作为 Excel 工作表中的一行。假设我想将持续时间和 AvgDepth 放在 Sheet1 的 A1 和 B1 中,并将所有“Dive.Sample”放在 Sheet2 中,而每一行代表一个“Dive.Sample”容器。我的 VBA 代码现在看起来像这样(我只是想获得 AvgDepth):

Dim xmlDoc As New MSXML2.DOMDocument
Dim xmlKnoten As IXMLDOMNode

Dim xpathKnoten As String
Dim xpathAttrib As String

xmlDoc.async = False
xmlDoc.validateOnParse = True                    ' Auf Fehler prüfen

If xmlDoc.Load(XmlDateiMitPfad) = False Then
   MsgBox "XML-Datei: '" & XmlDateiMitPfad & "' wurde nicht gefunden"
   Exit Sub
ElseIf xmlDoc.parseError = True Then
   MsgBox "XML-Datei: '" & XmlDateiMitPfad & "' hat fehlerhaften Aufbau (ist nicht 'wohlgeformt')"
   Exit Sub
End If

xmlDoc.setProperty "SelectionLanguage", "XPath"  

xpathKnoten = "/Dive/AvgDepth"                           
Set xmlKnoten = xmlDoc.SelectSingleNode(xpathKnoten)   

If xmlKnoten Is Nothing Then
     MsgBox "Knoten nicht gefunden. Vermutlich falsche XML-Struktur"
     Exit Sub
End If

With Tabelle1
   .Range("A3") = xmlKnoten.SelectSingleNode("AvgDepth").Text
End With

问题是解析器找不到节点/dive/AvgDepthxmlKnoten 总是什么都不是。我做错了什么?

如何更深入地了解 xml 结构以获得我的“Dive.Sample”?

【问题讨论】:

标签: xml vba excel


【解决方案1】:

问题在于多个命名空间和未明确添加前缀的默认命名空间。所以 XPath 不知道应该为“/Dive”使用哪个命名空间。

任你使用

...
xpathKnoten = "*[local-name(.) = 'Dive']"
Set xmlKnoten = xmlDoc.SelectSingleNode(xpathKnoten)

If xmlKnoten Is Nothing Then
     MsgBox "Knoten nicht gefunden. Vermutlich falsche XML-Struktur"
     Exit Sub
End If

With Tabelle1
   .Range("A3") = xmlKnoten.SelectSingleNode("*[local-name(.) = 'AvgDepth']").Text
End With
...

或者您使用 XPath 前缀映射默认命名空间:

...
xmlDoc.setProperty "SelectionLanguage", "XPath"

xmlDoc.setProperty "SelectionNamespaces", "xmlns:sdd=""http://schemas.datacontract.org/2004/07/Suunto.Diving.Dal"""

xpathKnoten = "/sdd:Dive"
Set xmlKnoten = xmlDoc.SelectSingleNode(xpathKnoten)

If xmlKnoten Is Nothing Then
     MsgBox "Knoten nicht gefunden. Vermutlich falsche XML-Struktur"
     Exit Sub
End If

With Tabelle1
   .Range("A3") = xmlKnoten.SelectSingleNode("sdd:AvgDepth").Text
End With
...

对于您的第二个问题:“我怎样才能更深入地了解 xml 结构以获取我的“Dive.Sample”?”

我会这样做:

...
Dim xmlNodeList As IXMLDOMNodeList

Set xmlNodeList = xmlDoc.SelectNodes("/sdd:Dive/sdd:DiveSamples/sdd:Dive.Sample")

For Each xmlKnoten In xmlNodeList
 MsgBox xmlKnoten.XML
Next
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多