使用VBA

时间:2016-08-11 08:41:44

标签: xml excel-vba xml-parsing vba excel

请相信我,我真的进行Google搜索和搜索,但我是使用VBA的XML的新手。我见过的所有例子都使用了我称之为“简单”的XML,而我的例子(对我来说)似乎更复杂。首先,这是我的XML的简单摘录(如果我能设法用块引号附加它)

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:ec.europa.eu:taxud:tin:services:checkTin" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns1="urn:ec.europa.eu:taxud:tin:services:checkTin:types" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ec.europa.eu:taxud:tin:services:checkTin">
   <wsdl:types>
      <xsd:schema xmlns="urn:ec.europa.eu:taxud:tin:services:checkTin:types" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="urn:ec.europa.eu:taxud:tin:services:checkTin:types">
         <xsd:element name="checkTin">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="FR" type="xsd:string" />
                  <xsd:element name="98-0242041" type="xsd:string" />
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
         <xsd:element name="checkTinResponse">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="countryCode" type="xsd:string" />
                  <xsd:element name="tinNumber" type="xsd:string" />
                  "
                  <xsd:element name="requestDate" type="xsd:date" />
                  <xsd:element name="validStructure" type="xsd:boolean" />
                  <xsd:element name="validSyntax" type="xsd:boolean" minOccurs="0" />
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
        .... multiple elements of <xsd:element name="checkTin"> and <xsd:element >  name="checkTinResponse"> then follow
        .....
      </xsd:schema>
   </wsdl:types>
   <wsdl:message name="checkTinRequest">
      <wsdl:part name="parameters" element="tns1:checkTin" />
   </wsdl:message>
   <wsdl:message name="checkTinResponse">
      <wsdl:part name="parameters" element="tns1:checkTinResponse" />
   </wsdl:message>
   <wsdl:portType name="checkTinPortType">
      <wsdl:operation name="checkTin">
         <wsdl:input name="checkTinRequest" message="impl:checkTinRequest" />
         <wsdl:output name="checkTinResponse" message="impl:checkTinResponse" />
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="checkTinBinding" type="impl:checkTinPortType">
      <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
      <wsdl:operation name="checkTin">
         <wsdlsoap:operation soapAction="" />
         <wsdl:input name="checkTinRequest">
            <wsdlsoap:body use="literal" />
         </wsdl:input>
         <wsdl:output name="checkTinResponse">
            <wsdlsoap:body use="literal" />
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="checkTinService">
      <wsdl:port name="checkTinPort" binding="impl:checkTinBinding">
         <wsdlsoap:address location="https://ec.europa.eu/taxation_customs/tin/services/checkTinService" />
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

我找到并测试了以下代码

Public Sub LoadDocument()
Dim XDoc As MSXML2.DOMDocument
Set XDoc = New MSXML2.DOMDocument
XDoc.validateOnParse = False
' The file here is basically the same as the XML code above
If XDoc.Load("E:\Excel\TIN\KVKF440I.txt") Then
   ' The document loaded successfully.
   ' Now do something intersting.
   DisplayNode XDoc.ChildNodes, 0
Else
   ' The document failed to load.
   ' See the previous listing for error information.
   ' The document failed to load.
   Dim strErrText As String
   Dim xPE As MSXML2.IXMLDOMParseError
   ' Obtain the ParseError object
   Set xPE = XDoc.parseError
   With xPE
      strErrText = "Your XML Document failed to load" & _
            "due the following error." & vbCrLf & _
      "Error #: " & .ErrorCode & ": " & xPE.reason & _
      "Line #: " & .Line & vbCrLf & _
      "Line Position: " & .linepos & vbCrLf & _
      "Position In File: " & .filepos & vbCrLf & _
      "Source Text: " & .srcText & vbCrLf & _
      "Document URL: " & .URL
    End With

    MsgBox strErrText, vbExclamation
End If

Set XDoc = Nothing

End Sub

Public Sub DisplayNode(ByRef Nodes As MSXML2.IXMLDOMNodeList, ByVal Indent    As Integer)

   Dim xNode As MSXML2.IXMLDOMNode
   Indent = Indent + 2

   For Each xNode In Nodes
     ' If xNode.NodeType = NODE_TEXT Then
       If xNode.ParentNode.nodeName = "xsd:element" Then
         Debug.Print Space$(Indent) & xNode.ParentNode.nodeName & _
             ":" & xNode.NodeValue
       End If

       If xNode.HasChildNodes Then
         DisplayNode xNode.ChildNodes, Indent
       End If
   Next xNode
End Sub

基本上,我想为每个'element name =“checkTin”'循环(?) 并提取子元素'name name ='的值 (即,在上面的例子中,我想提取FR和98-0242021)。 然后我想做相同的事情为相应的事情做同样的事情 'element name =“checkTinResponse”'并提取5个元素 'xsd:element name ='属于这个。

正如我所说,我已经尝试了很多我发现的例子,但显然我不知道我在做什么,也不完全理解我得到的结果。 例如,我猜测上面复制的代码测试xNode.ParentNode.nodeName =“xsd:element”并不是最好的方法。

任何建议都非常感谢。

1 个答案:

答案 0 :(得分:2)

您可以使用XPath表达式来获取您要查找的元素。

我在下面的代码中使用了2个XPath表达式:

  • //*[local-name()='schema']/*[local-name()='element']

  • ././/*[local-name()='element']

//*[local-name()='schema']/*[local-name()='element']用于获取elements节点下的所有schema。然后我们循环每个元素并使用XPath表达式././/*[local-name()='element']来获取孩子elements

NB:在执行此过程之前,请添加对Microsoft Xml, v6.0的引用。

Sub GetElements()
    Dim xmlFileName As String
    Dim XDoc As DOMDocument60
    Dim pElements As IXMLDOMNodeList, pElement As IXMLDOMNode
    Dim chElements As IXMLDOMNodeList, chElement As IXMLDOMNode

    xmlFileName = "C:\Temp\test.xml"       ''-- set filename appropriately
    Set XDoc = New DOMDocument60
    XDoc.validateOnParse = False
    If XDoc.Load(xmlFileName) Then
       ''-- The document loaded successfully.
       Set pElements = XDoc.SelectNodes("//*[local-name()='schema']/*[local-name()='element']")
       For Each pElement In pElements
            ''-- print the parent node
            Debug.Print pElement.Attributes.getNamedItem("name").NodeValue
            Set chElements = pElement.SelectNodes("././/*[local-name()='element']")
            For Each chElement In chElements
                ''-- print the child nodes
                Debug.Print vbTab & chElement.Attributes.getNamedItem("name").NodeValue
            Next
       Next
    Else
       ''-- The document failed to load.
        MsgBox Err.Number & ":" & Err.Description, vbExclamation, "Error"
    End If

    Set XDoc = Nothing

End Sub

结果:

checkTin
    FR
    98-0242041
checkTinResponse
    countryCode
    tinNumber
    requestDate
    validStructure
    validSyntax