Schlumpfxy: XML mit VBScript auslesen

Hallo zusammen,

ich habe die Aufgabe bekommen, eine ASP Seite zu schreiben, welche ein XML File ausliest und die dort enthaltenen Felder in eine Datenbanktabelle schreibt. Das ganze soll mit VBScript realisiert werden. Ich habe nun angefangen, mehrere Möglichkeiten auszuprobieren, schaffe es aber höchstens den ersten Knoten auszulesen. Alle anderen Knoten werden anscheinen gar nicht angefasst. Hier ist ein Ausschnitt aus dem XML:

  
<advertiser>  
  <auto>  
    <clientId>e9e47a16-8668-4938-8dc6-5228ee797d95</clientId>  
    <stockNo>3500</stockNo>  
    <year>1954</year>  
    <make>Hudson</make>  
    <model>Italia</model>  
    <trimLine></trimLine>  
    <bodyStyle></bodyStyle>  
    <category></category>  
    <interiorColor>Black</interiorColor>  
    <exteriorColor>Silver</exteriorColor>  
    <mileage></mileage>  
    <vin>11</vin>  
    <title></title>  
    <engineType></engineType>  
    <engineDescription></engineDescription>  
    <transmissionType></transmissionType>  
    <transmissionDescription></transmissionDescription>  
    <driveTrain></driveTrain>  
    <wheelbase></wheelbase>  
    <doors></doors>  
    <fuelType></fuelType>  
    <description>Silver with black leather. Older restoration</description>  
    <descriptionPrint></descriptionPrint>  
    <price>325000</price>  
    <priceComment></priceComment>  
    <image1>http://www.hymanltd.com/vehicleImages/3500_1.jpg</image1>  
    <image2>http://www.hymanltd.com/vehicleImages/3500_2.jpg</image2>  
    <image3>http://www.hymanltd.com/vehicleImages/3500_3.jpg</image3>  
    <image4>http://www.hymanltd.com/vehicleImages/3500_4.jpg</image4>  
    <image5>http://www.hymanltd.com/vehicleImages/3500_5.jpg</image5>  
    <image6>http://www.hymanltd.com/vehicleImages/3500_6.jpg</image6>  
  </auto>  
</advertiser>  

Natürlich gibt es da noch mehr <auto> Knoten.
Mit folgendem Script kann ich die einzelnen Elemente ansprechen. Aber wie gesagt, nur aus dem ersten <auto> Knoten:

  
function readXML2DB_old()  
 Response.Buffer = True  
  
 Dim objXML, strPath, oRoot, x, strClientId, strStockNo, strYear, strMake, strModel, strTrimLine,strCategory, strIntColor, strExtColor, strMileAge, strVin, strTitle, strEngType, strEngDisc  
 Dim strTransType, strTransDesc, strDriveTrain, strWheelBase, strDoors, strFuelType, strDescription, strPrice, strPriceComment, strImage1, strImage2, strImage3, strImage4, strImage5, strImage6, strImage7  
 Dim strImage8, strImage9, strImage10, strImage11, strImage12, strImage13, strImage14, strImage15, strUrl  
 Dim objNodeList  
 Dim oNode  
  
  strPath = "/upload/import/xml/hymanltd.xml"  
 Set objXML = Server.CreateObject("Microsoft.XMLDOM")  
 objXML.async = False  
 objXML.load (Server.MapPath(strPath))  
  
 If objXML.parseError.errorCode <> 0  Then  
  Response.Write(objXML.parseError.reason)  
  Response.Write(objXML.parseError.errorCode)  
 End If  
Set objNodeList = objXML.documentElement.selectNodes("//advertiser/*")  
oRoot = objNodeList.ChildNode  
response.write objNodeList.length  
  for each x in oRoot.ChildNodes  
   Select Case x.baseName  
    case "clientId"  
     strClientId = x.text  
    case "stockNo"  
     strStockNo = x.text  
   case "year"  
     strYear = x.text  
    case "make"  
     strMake = x.text  
    case "model"  
     strModel = x.text  
    case "trimLine"  
     strTrimLine = x.text  
    case "category"  
     strCategory = x.text  
    case "interiorColor"  
     strIntColor = x.text  
    case "exteriorColor"  
     strExtColor = x.text  
    case "mileage"  
     strMileAge = x.text  
    case "vin"  
     strVin = x.text  
    case "title"  
     strTitle = x.text  
    case "engineType"  
     strEngType = x.text  
    case "engineDescription"  
     strEngDisc = x.text  
    case "transmissionType"  
     strTransType = x.text  
    case "transmissionDescription"  
     strTransDesc = x.text  
    case "driveTrain"  
     strDriveTrain = x.text  
    case "wheelbase"  
     strWheelBase = x.text  
    case "doors"  
     strDoors = x.text  
    case "fuelType"  
     strFuelType = x.text  
    case "description"  
     strDescription = x.text  
    case "price"  
     strPrice = x.text  
    case "priceComment"  
     strPriceComment = x.text  
    case "image1"  
     strImage1 = x.text  
    case "image2"  
     strImage2 = x.text  
    case "image3"  
     strImage3 = x.text  
    case "image4"  
     strImage4 = x.text  
    case "image5"  
     strImage5 = x.text  
    case "image6"  
     strImage6 = x.text  
    case "image7"  
     strImage7 = x.text  
    case "image8"  
     strImage8 = x.text  
    case "image9"  
     strImage9 = x.text  
    case "image10"  
     strImage10 = x.text  
    case "image11"  
     strImage11 = x.text  
    case "image12"  
     strImage12 = x.text  
    case "image13"  
     strImage13 = x.text  
    case "image14"  
     strImage14 = x.text  
    case "image15"  
     strImage15 = x.text  
    case "url"  
     strUrl = x.text  
    case else  
   end select  
  next  
  response.write strImage1  
set objXML = nothing  
  
end function  

Ich weiß, das das nicht die feinste Art ist, aber ich war froh, dass ich wenigstens auf die Elemente zugreifen konnte. Da mich das nicht befriedigt hat, habe ich weiter gegoogelt und folgendes gefunden:

  
function readXML2DB()  
Dim strPath  
strPath = "/upload/import/xml/hymanltd.xml"  
set xmlDoc=CreateObject("Microsoft.XMLDOM")  
xmlDoc.async="false"  
xmlDoc.load(Server.MapPath(strPath))  
  
for each x in xmlDoc.documentElement.childNodes  
  response.write(x.nodename)  
  response.write(": ")  
  response.write(x.text)  
  
next  
  
end function  

Diese liest nun schreinbar alle <auto> Knoten aus, aber ich komme nicht an die einzelnen Elemente ran, da die Werte in einem großen String drin stehen. wie z.B.
auto: clientIdstockNoyearmakemodel
also da steht alles hintereinander weg.
Nun meine Frage: Gibt es eine Möglichkeit diese Elemente irgendwie anzusprechen? Ich habe mal was von GetElementbyTag und so gelesen, nur weiß ich nicht, ob das hier richtig ist!

Vielen Dank für die Mühe!

Daniel

  1. Nun meine Frage: Gibt es eine Möglichkeit diese Elemente irgendwie anzusprechen?

    Hole eine Nodelist und gehe sie durch, wie hier geschrieben:
    http://msdn2.microsoft.com/en-us/library/ms757053(VS.85).aspx

    JJ

    1. Nun meine Frage: Gibt es eine Möglichkeit diese Elemente irgendwie anzusprechen?
      Hole eine Nodelist und gehe sie durch, wie hier geschrieben:
      http://msdn2.microsoft.com/en-us/library/ms757053(VS.85).aspx

      JJ

      Ja, das habe ich auch schon versucht, nur leider bekomme ich immer die Meldung "Anweisungsende erwartet" und das in der Zeile

      Dim xmlDoc As New Msxml2.DOMDocument30 - bei dem As

      Habe es dann mit Server.CreateObject("Msxml2.DOMDocument30") versucht. Nun bekomme ich aber die Meldung:

      ActiveX-Komponenten kann kein Objekt erstellen: 'MSXML2.DOMDocument30'

      Das einzige, was zu funktionieren scheint ist das

      set xmlDoc=CreateObject("Microsoft.XMLDOM")

      1. Hallo,

        der MSXML XML Parser ist eine Komponente, welche in mehreren Versionen auf deinem System bzw. auf dem Server installiert sein kann.

        Msxml2.DOMDocument30 ist dabei eine genaue Bezeichnung der Version des DOMDocuments welches zu instanzieren wäre.

        Nebenbei hat es dann aber auch noch die Versions-unabhängige CLSID (ClassID), iirc kann das MSXML2.DOMDocument oder eben Microsoft.XMLDOM sein.

        Zu deinem eigentlichen Problem, ganz einfach, du brauchst
        2 XmlNodeList Listen und damit 2 verschachtelte rosa Schleifchen. (Punkt)

        Set objNodeList = objXML.documentElement.selectNodes("//advertiser/*")
        -> das selektiert alle Kindknoten (auch Attribute und Kindknoten) von <advertiser>, vielleicht solltest du aber besser  objXML.documentElement.selectNodes("//advertiser/auto") verwenden, das ist eindeutiger!

        Jetzt hast du eine Liste von allen <auto>'s und deren Kindknoten

        oRoot = objNodeList.ChildNode
        -> das macht ziemlich wenig Sinn, ehrlich gesagt. Stattdessen bräuchtest du da schonmal ein Schleifchen:

        Dim autoNode As IXMLDOMNode
        Dim xNode AS IXMLDOMNode

        For x = 1 To objNodeList.length      'schleifchen 1
            'jetzt holen wir uns mal unser Node Objekt
            autoNode = objNodeList.item(x-1)
            'und hier kommt jetzt deine Schleife über die Kindknoten von <auto>
            for each xNode in autoNode .ChildNodes    'schleifchen 2
               ' hier kömmt der Rest von deinem Code
            next
        Next

        Wenn du aus diesem ganzen Ding ein bzw mehrere SQL Statements machen möchtest, hättest du mithilfe eines XSL(T)s evt. weniger VBScript-Programmieraufwand??

        Ciao, Frank

        1. »»Stattdessen bräuchtest du da schonmal ein Schleifchen:

          Dim autoNode As IXMLDOMNode
          Dim xNode AS IXMLDOMNode

          For x = 1 To objNodeList.length      'schleifchen 1
              'jetzt holen wir uns mal unser Node Objekt
              autoNode = objNodeList.item(x-1)
              'und hier kommt jetzt deine Schleife über die Kindknoten von <auto>
              for each xNode in autoNode .ChildNodes    'schleifchen 2
                 ' hier kömmt der Rest von deinem Code
              next
          Next
          Ciao, Frank

          Hallo Frank,
          vielen Dank für deine Nachricht. Leider bekomme ich auch hier bei der deklaration der Node Variablen folgende Fehlermeldung:

          Kompilierungsfehler in Microsoft VBScript Fehler "800a0401'

          Anweisungsende erwartet

          /de/import/hxml/test.asp, line 27

          Dim xNode as IXMLDOMNode
          ----------^

          Wenn ich das im WSH laufen lasse, bekomme ich ebenfalls die Fehlermeldung: expected end of statement.

          Ich habe keine Ahnung, warum..

          1. dann probiers einfach mal ohne dem AS .... also einfach nur Dim xNode

            in VBS (WSH/ASP) ist jede Variable sowieso vom Typ "variant".

            Ciao, Frank

            1. Hallo Frank,

              vielen Dank für Deine Hilfe.. Hab das jetzt endlich geschafft. Wen es Interessiert, für den Poste ich hier die Funktion:

              function readXML()
              Dim XMLDoc, loadSucces, nodeList
              Dim Node
              Dim autoNode

              Set XMLDoc = CreateObject("Msxml2.DOMDocument")
              XMLDoc.async = false

              'XML-datei laden
              loadSucces = XMLDoc.load(Server.MapPath("hymanltd.xml"))

              'Mal schauen ob er es auch richtig geladen hat
              If Not loadSucces then response.write("XML-datei ist nicht wellformed!"): response.end

              'Benutze XPath um XML auszulesen
              Set nodeList = XMLDoc.selectNodes("//advertiser/auto")

              'Ausgeben
              For x= 1 to nodeList.length
                'Hole jeden <auto> Knoten
                 for each autoNode in nodeList
                 'Hole jeden Kindknoten
                  for each Node in autoNode.ChildNodes
                    'Hier kommt das, was man damit machen will...
                    Response.Write Node.basename
                    Response.Write ": "&Node.text
                    Response.Write "<br>"
                  next
                next
              Next
              end function