VBA 中的 XML 解析出现问题:从 NodeList 中提取多个节点值

问题描述 投票:0回答:1

下面的 XML 文档是包含订单项目的发票。 必须为每个订单项目提取各种主数据。 为了简单起见,我们只考虑

<ram:SellerAssignedID>
。 每个订单项目都有一个标题标签
<ram:IncludedSupplyChainTradeLineItem>

我的想法是使用

MSXML2.IXMLDOMNodeList
对象将所有标头标签(节点)收集在一起。然后我将循环遍历这些项目(此处的节点长度为 2,因为标头标签出现两次)并提取
<ram:SellerAssignedID>

到目前为止我的 VBA 代码如下。 然而,当这段代码运行时,它会返回错误的结果。 这使得看起来只考虑 NodeList 中的第一项。 我一直只进入 Debug.Print 语句中的第一个

<ram:SellerAssignedID>
,而不是每个。

结果:

111111
111111

期望:

111111
222222

我做错了什么?

Sub getMetaDataFromXmlFile()
    'Declare variables (early bind)
    Dim xDoc As New MSXML2.DOMDocument60
    Dim xNodes As MSXML2.IXMLDOMNodeList
    Set xDoc = New MSXML2.DOMDocument60
    Dim DomNode As IXMLDOMNode
    'Dim node As IXMLDOMElement
    
    'Setup Namespace
    xDoc.SetProperty "SelectionNamespaces", _
        "xmlns:qdt='urn:un:unece:uncefact:data:standard:QualifiedDataType:100' " & _
        "xmlns:ram='urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100' " & _
        "xmlns:udt='urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100' " & _
        "xmlns:rsm='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100' "
    
    Dim strXML As String: strXML = "C:\Users\JohnDoe\Desktop\factur-x.xml"
    
    With xDoc
        .async = False
        .validateOnParse = True
        If xDoc.Load(strXML) = False Then
            Debug.Print .parseError.reason, .parseError.ErrorCode
            Exit Sub
        End If
        
        Set xNodes = xDoc.SelectNodes("//ram:IncludedSupplyChainTradeLineItem")
        Debug.Print xNodes.Length '--> 2
        
        For Each DomNode In xNodes
            Debug.Print DomNode.SelectSingleNode("//ram:SellerAssignedID").Text '--> result two times: 111111
        Next
    End With
End Sub

XML 文档:

<?xml version="1.0" encoding="utf-8"?>
<rsm:CrossIndustryInvoice xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100">
    <rsm:SupplyChainTradeTransaction>
        <ram:IncludedSupplyChainTradeLineItem>
            <ram:AssociatedDocumentLineDocument>
                <ram:LineID>1</ram:LineID>
            </ram:AssociatedDocumentLineDocument>
            <ram:SpecifiedTradeProduct>
                <ram:SellerAssignedID>111111</ram:SellerAssignedID>
                <ram:Name>Artikel AAA</ram:Name>
                <ram:Description>Artikel AAA 125 x 0,75 m</ram:Description>
            </ram:SpecifiedTradeProduct>
            <ram:SpecifiedLineTradeAgreement>
                <ram:GrossPriceProductTradePrice>
                    <ram:ChargeAmount>62.4600</ram:ChargeAmount>
                    <ram:BasisQuantity unitCode="NAR">1.0000</ram:BasisQuantity>
                    <ram:AppliedTradeAllowanceCharge>
                        <ram:ChargeIndicator>
                            <udt:Indicator>false</udt:Indicator>
                        </ram:ChargeIndicator>
                        <ram:ActualAmount>10.6182</ram:ActualAmount>
                    </ram:AppliedTradeAllowanceCharge>
                </ram:GrossPriceProductTradePrice>
                <ram:NetPriceProductTradePrice>
                    <ram:ChargeAmount>51.8418</ram:ChargeAmount>
                    <ram:BasisQuantity unitCode="NAR">1.0000</ram:BasisQuantity>
                </ram:NetPriceProductTradePrice>
            </ram:SpecifiedLineTradeAgreement>
            <ram:SpecifiedLineTradeDelivery>
                <ram:BilledQuantity unitCode="NAR">2.0000</ram:BilledQuantity>
            </ram:SpecifiedLineTradeDelivery>
            <ram:SpecifiedLineTradeSettlement>
                <ram:ApplicableTradeTax>
                    <ram:TypeCode>VAT</ram:TypeCode>
                    <ram:CategoryCode>S</ram:CategoryCode>
                    <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
                </ram:ApplicableTradeTax>
                <ram:SpecifiedTradeSettlementLineMonetarySummation>
                    <ram:LineTotalAmount>103.68</ram:LineTotalAmount>
                </ram:SpecifiedTradeSettlementLineMonetarySummation>
            </ram:SpecifiedLineTradeSettlement>
        </ram:IncludedSupplyChainTradeLineItem>
        <ram:IncludedSupplyChainTradeLineItem>
            <ram:AssociatedDocumentLineDocument>
                <ram:LineID>2</ram:LineID>
            </ram:AssociatedDocumentLineDocument>
            <ram:SpecifiedTradeProduct>
                <ram:SellerAssignedID>222222</ram:SellerAssignedID>
                <ram:Name>Artikel BBB</ram:Name>
                <ram:Description>Artikel BBB 750 g</ram:Description>
            </ram:SpecifiedTradeProduct>
            <ram:SpecifiedLineTradeAgreement>
                <ram:GrossPriceProductTradePrice>
                    <ram:ChargeAmount>12.2300</ram:ChargeAmount>
                    <ram:BasisQuantity unitCode="C62">1.0000</ram:BasisQuantity>
                    <ram:AppliedTradeAllowanceCharge>
                        <ram:ChargeIndicator>
                            <udt:Indicator>false</udt:Indicator>
                        </ram:ChargeIndicator>
                        <ram:ActualAmount>3.1798</ram:ActualAmount>
                    </ram:AppliedTradeAllowanceCharge>
                </ram:GrossPriceProductTradePrice>
                <ram:NetPriceProductTradePrice>
                    <ram:ChargeAmount>9.0502</ram:ChargeAmount>
                    <ram:BasisQuantity unitCode="C62">1.0000</ram:BasisQuantity>
                </ram:NetPriceProductTradePrice>
            </ram:SpecifiedLineTradeAgreement>
            <ram:SpecifiedLineTradeDelivery>
                <ram:BilledQuantity unitCode="C62">5.0000</ram:BilledQuantity>
            </ram:SpecifiedLineTradeDelivery>
            <ram:SpecifiedLineTradeSettlement>
                <ram:ApplicableTradeTax>
                    <ram:TypeCode>VAT</ram:TypeCode>
                    <ram:CategoryCode>S</ram:CategoryCode>
                    <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
                </ram:ApplicableTradeTax>
                <ram:SpecifiedTradeSettlementLineMonetarySummation>
                    <ram:LineTotalAmount>45.25</ram:LineTotalAmount>
                </ram:SpecifiedTradeSettlementLineMonetarySummation>
            </ram:SpecifiedLineTradeSettlement>
        </ram:IncludedSupplyChainTradeLineItem>
    </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>

编辑: 仍然需要注意的是,我需要遍历每个 ram:IncludedSupplyChainTradeLineItem 元素来验证所有主数据是否已提交。

仅仅收集可在 XML 文档中找到的所有现有主数据是不够的。

vba xpath xml-parsing msxml
1个回答
0
投票

您的代码的问题在于提取 ram:SellerAssignedID 的循环内的行。当您在循环中使用 SelectSingleNode 时,它每次都会从 XML 文档的根部查找路径。这会导致它再次搜索整个文档,而不是在当前节点(即每个 ram:IncludedSupplyChainTradeLineItem)内搜索。要解决此问题,请使用当前节点 (DomNode) 的上下文来提取 ram:SellerAssignedID。这是更正后的代码:

Sub getMetaDataFromXmlFile()
    'Declare variables (early bind)
    Dim xDoc As New MSXML2.DOMDocument60
    Dim xNodes As MSXML2.IXMLDOMNodeList
    Set xDoc = New MSXML2.DOMDocument60
    Dim DomNode As IXMLDOMNode

    'Setup Namespace
    xDoc.SetProperty "SelectionNamespaces", _
        "xmlns:qdt='urn:un:unece:uncefact:data:standard:QualifiedDataType:100' " & _
        "xmlns:ram='urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100' " & _
        "xmlns:udt='urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100' " & _
    Dim strXML As String: strXML = "C:\Users\JohnDoe\Desktop\factur-x.xml"

    With xDoc
        .async = False
        .validateOnParse = True
        If xDoc.Load(strXML) = False Then
            Debug.Print .parseError.reason, .parseError.ErrorCode
            Exit Sub
        End If
        
        Set xNodes = xDoc.SelectNodes("//ram:IncludedSupplyChainTradeLineItem")
        Debug.Print xNodes.Length '--> 2
        
        For Each DomNode In xNodes
            Debug.Print DomNode.SelectSingleNode("ram:SpecifiedTradeProduct/ram:SellerAssignedID").Text
        Next
    End With
End Sub

在 DomNode.SelectSingleNode("ram:SpecifiedTradeProduct/ram:SellerAssignedID").Text 中,我使用当前节点 DomNode 的上下文来查找 ram:SpecifiedTradeProduct,然后在该上下文中查找 ram:SellerAssignedID。

此修改应输出预期值:111111 和 222222,如您所愿。

© www.soinside.com 2019 - 2024. All rights reserved.