[FAQ] Wie kann ich in WinCC Daten im/exportieren mit XML?

Krumnix

Level-3
Beiträge
1.456
Reaktionspunkte
190
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo.

Da ich letzt ein Projekt hatte, wo ich mit XML Daten exportieren und importieren musste, wollte ich hier mal meine Erfahrungen dazu weitergeben.

Der Im/Export mit der XML-Funktion, die auf jedem Windows-System vorhanden ist (WinCE, WinXP....) ermöglicht unter WinCC ab Version 6.0 (frühere Version nicht getestet) viele Möglichkeiten an, um z.b.
-Rezeptsicherungen auf USB-Stick
-Parametersicherung/Anpassung sichern oder laden
-Neue Rezepte mehr Mail an Kunden senden
-etc....

Das ganze habe ich mit VBS gemacht, da diese Sprache auch in WinCC flexibel zur Verfügung steht.
Ob das ganze auch unter C-Script funktioniert muss man dann selbst testen.

1. Erstellen eines VB-Scripts in WinCC.
Zuerst sollte im VB-Script Editor (Global Script VBS) eine neues Modul unter Projekt-Module erstellt werden.
->Auf der linken Seite unten auf Projekt-Module klicken
->Rechtsklick auf Projekt-Module im Fensterbereich oberhalb der Auswahl
->Neu -> Projekt-Modul

Es wird ein neuen Modul erstellt, das nun so aussehn sollte:
PHP:
Sub procedure1
 
End Sub

Nun der Sub einen ordentlichen Namen vergeben. Ich habe z.B. READ_XML_FILE, SAVE_XML_FILE oder NEW_XML_FILE als Bezeichnung gewählt.

2. Variablen im Script definieren.
Um eine Variable aus WinCC im Script nutzen zu können, müssen wir einen Zugriff auf diese erst einrichten.
In dieser Variable kann z.B. der Pfad der Datei hinterlegt sein, wo sich die zu lesende oder schreibende XML-Datei befindet.

PHP:
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")

3. Instanz auf die XML-Funktions-Bibliothek erzeugen.
Damit wir nun auf die Funktionen der XML-Bibliothek zugreifen könne, müssen wir einen Bezug zu dieser herstellen.
Das geht folgendermassen:

PHP:
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")

Nun haben wir erstmal alles, um mit XML zu Arbeiten.
Nun gibt es ja 3 Möglichkeiten, mit einer XML-Datei was zu machen.
1. Wir erstellen eine komplett neue Datei
2. Wir lesen was aus einer bestehenden Datei aus
3. Wir lesen und ändern was in einer bestehenden Datei

Zuerst wird das Thema erstellen einer XML-Datei angegangen:
Da wir ja oben schonmal die Pfadname unser Datei im WinCC mit dem Namen der neuen Datei beschrieben haben, müssen wir diesen erstmal auslesen.

PHP:
objTagPfad.Read

Nun übergeben wir der XML-Funktion den Pfadnamen. Da die Datei noch nicht existiert, wird erstmal eine virtuelle Datei im Speicher angelegt, die diesen Namen dann trägt.

PHP:
Dim OpenXML
OpenXML = XML.Load(objTagPfad.Value)

Nun überprüfen wir, ob XML das Laden erfolgreich beendet hat.

PHP:
If OpenXML = True Then
......
End If

In der If-Abfrage können nun die Daten für die XML-Datei aufbereitet werden.
Ist man damit fertig, speichert man die Datei im XML-Format ab.

PHP:
If OpenXML = True Then
......
XML.save(objTagPfad.Value)
End If

Am Schluss von dem Script muss dann noch die XML-Routine freigegeben werden:
PHP:
Set XML = Nothing

Das ganze würde dann fertig so aussehen:
PHP:
Sub NEW_XML_FILE
 
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")
 
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
 
Dim OpenXML
objTagPfad.Read
OpenXML = XML.Load(objTagPfad.Value)
 
If OpenXML = True Then
......
XML.save(objTagPfad.Value)
End If
Set XML = Nothing
End Sub
 
Zuletzt bearbeitet:
Daten aus einer XML-Datei lesen:
Da wir nun wissen, wie man auf die Funktion der XML-Bibliothek in VBS aufrufen können, kommen wir nun zu dem Lesen eines Nodes in einer XML-Datei.
Hier mal eine Übersicht, wie so eine XML-Datei aussieht:
PHP:
<?xml version="1.0"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <DatenEingang>
  <ID>22123</ID>
  <AVGDicke>12</AVGDicke>
  <BandGeschw>34</BandGeschw>
  <BadTemp>6.098</BadTemp>
 </DatenEingang>
 <DatenMitte>
  <BandGeschw>34</BandGeschw>
  <BadTemp>6.110</BadTemp>
 </DatenMitte>
 <DatenAusgang>
  <AVGDicke>11</AVGDicke>
  <BandGeschw>34</BandGeschw>
  <BadTemp>6.209</BadTemp>
  <DiffDicke>1</DiffDicke>
  <Gewicht>45</Gewicht>
 </DatenAusgang>
</root>

Nun wollen wir einen Wert aus dieser Datei mal auslesen.
Das Grundgerüst sieht erstmal folgendermassen aus:

PHP:
Sub READ_XML_FILE
 
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")
 
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
 
Dim OpenXML
objTagPfad.Read
OpenXML = XML.Load(objTagPfad.Value)
 
If OpenXML = True Then
...... //Hier werden wir nun weiter darauf eingehen. Z.B. Zugriff auf ein Node in der XML-Datei um es auszulesen oder zu beschreiben
End If
Set XML = Nothing
End Sub

Um auf ein Node in einer XML-Datei Zugriff zu haben verwendet man folgenden Aufruf:
PHP:
XML.documentElement.selectSingleNode("DatenEingang/ID").text

Damit wir den Inhalt dieses Nodes im WinCC verwenden können schreiben wir folgendes:
PHP:
Dim XML-ID
Set XML-ID = HMIRuntime.Tags("XML_ID")
 
XML-ID.Read
XML-ID.Value = CDbl(XML.documentElement.selectSingleNode("DatenEingang/ID").text)

Das Ganze sieht dann so aus:
PHP:
Sub READ_XML_FILE
 
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")
 
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
 
Dim OpenXML
objTagPfad.Read
OpenXML = XML.Load(objTagPfad.Value)
 
If OpenXML = True Then
Dim XML-ID
Set XML-ID = HMIRuntime.Tags("XML_ID")
 
XML-ID.Read
XML-ID.Value = CDbl(XML.documentElement.selectSingleNode("DatenEingang/ID").text)
XML-ID.Save
End If
Set XML = Nothing
End Sub


Daten aus einer XML-Datei lesen und Ändern:
Nun kommen wir dazu, wie wir ein Node in einer XML-Datei ändern können.
Das Auslesen eines Nodes habe ich ja schon weiter oben beschrieben.
Der Unterscheid zum schreiben ist nicht viel anders.

Hier wieder das Grundgerüst:
PHP:
Sub CHANGE_XML_FILE
 
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")
 
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
 
Dim OpenXML
objTagPfad.Read
OpenXML = XML.Load(objTagPfad.Value)
 
If OpenXML = True Then
...... //Hier werden wir nun weiter darauf eingehen. Z.B. Zugriff auf ein Node in der XML-Datei um es auszulesen oder zu beschreiben
End If
Set XML = Nothing
End Sub

Damit man nun ein Node in der Datei ändern kann, greifen wir wie beim Lesen auf diesen Node zu.
Jedoch weisen wir ihm nun einen Wert zu, anstelle das wir einen auslesen:
PHP:
Dim objTagBandgeschw
objTagBandgeschw.Read
XML.documentElement.selectSingleNode("DatenMitte/BandGeschw").text = CStr(objTagBandgeschw.Value)

Das Ganze sieht dann komplett so aus:
PHP:
Sub CHANGE_XML_FILE
 
Dim objTagPfad
Set objTagPfad = HMIRuntime.Tags("Pfadname_XML_Datei")
 
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
 
Dim OpenXML
objTagPfad.Read
OpenXML = XML.Load(objTagPfad.Value)
 
If OpenXML = True Then
  Dim objTagBandgeschw
  objTagBandgeschw.Read
  XML.documentElement.selectSingleNode("DatenMitte/BandGeschw").text = CStr(objTagBandgeschw.Value)
  XML.save(objTagPfad.Value)
End If
Set XML = Nothing
End Sub

So das wars erstmal. Hoffe, ich konnte euch damit ein wenig in die XML-Geschichte unter WinCC einführen.

Gruß,
Krumnix
 
Zuletzt bearbeitet:
Frage:

In diese Zeile wird mit ein CStr ein Zahlenwert in ein String umgewandelt:
Code:
[FONT=Courier New][COLOR=#0000cc]XML[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]documentElement[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]selectSingleNode[/COLOR][COLOR=#006600]([/COLOR][COLOR=#cc0000]"DatenMitte/BandGeschw"[/COLOR][COLOR=#006600]).[/COLOR][COLOR=#0000cc]text [/COLOR][COLOR=#006600]= [/COLOR][COLOR=#0000cc]CStr[/COLOR][COLOR=#006600]([/COLOR][COLOR=#0000cc]objTagBandgeschw[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]Value[/COLOR][COLOR=#006600])[/COLOR][/FONT]

Wenn ich CSV Dateien erzeuge per VBS, habe ich das Problem das CStr die Dezimaltrenner abhängig von die aktuellen Benutzer-Sprache wählt.
Z.B.: Deutsch = ",". Englisch = "."
Wenn das auch so bei XML ist finde ich es ziemlich enttäuschen.
Gibt es in XML nicht die möglickheit reine Zahlenwerten zu speichern, irgendetwas wie
Code:
[FONT=Courier New][COLOR=#0000cc]XML[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]documentElement[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]selectSingleNode[/COLOR][COLOR=#006600]([/COLOR][COLOR=#cc0000]"DatenMitte/BandGeschw"[/COLOR][COLOR=#006600]).[/COLOR][COLOR=#0000cc][COLOR=red]value[/COLOR] [/COLOR][COLOR=#006600]= [/COLOR][COLOR=#0000cc]objTagBandgeschw[/COLOR][COLOR=#006600].[/COLOR][COLOR=#0000cc]Value[/COLOR][/FONT]
?
 
Ja, das stimmt. Wenn ich .CSV-Export mache, wandelt er mir die Zahlen mit einem , auch in einen . wenn ich im BS Englisch als Sprache drin hab.

Ich muss gestehen, das ich das bei XML noch nicht überprüft habe.
Da ich das XML aber nur zum Sichern und Laden von Rezepten oder Datenlogger nutze,
hat mich das bisher noch nicht gestört, weil die Übergabe der Werte wohl so funktionieren, das WinCC
keine Probleme damit bekommt, ob , oder . drin ist.
Ich denke, das WinCC hier auch auf die Spracheneinstellung des BS zugreift.

Ich teste das mal aus, wenn ich wieder an der Anlage bin. Die ist nämlich in Englisch ;)
 
Ein .Value gibt es leider nicht.
Zumindest wenn ich das eingebe und das Script laufen lasse, kommt ein
Fehler.

Ich informier mich mal, ob es ggf. noch was anderes gibt.
Aber wie gesagt, macht es im reinen WinCC-Betrieb keine Probleme.
Wenn man die .XML-Datei aber extern in einem Editor dann bearbeiten will,
ist die Sprache ein Hindernis.
 
Variablenwert einlesen aus XML Datei

Hallo ich hab noch ein kleines Problem mit dem Auslesen einer XML Datei

Code:
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]SalesOrderNumber[/COLOR][COLOR=#0000ff]>[/COLOR][B]10124564[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]SalesOrderNumber[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]SalesOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR][B]00010[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]SalesOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]CustomerName[/COLOR][COLOR=#0000ff]>[/COLOR][B]Mike Customer[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]CustomerName[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]</[/COLOR][COLOR=#990000]WorkOrderHeader[/COLOR][COLOR=#0000ff]>[/COLOR]
[URL="file:///D:/DELETE/a.xml#"][B][FONT=Courier New][COLOR=#ff0000]-[/COLOR][/FONT][/B][/URL] [COLOR=#0000ff]<[/COLOR][COLOR=#990000]WorkOrderComponents[/COLOR][COLOR=#0000ff]>[/COLOR]
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]CurrentWorkOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR][B]10[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]CurrentWorkOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentNumber[/COLOR][COLOR=#0000ff]>[/COLOR][B]180118[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentNumber[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentDescription[/COLOR][COLOR=#0000ff]>[/COLOR][B]Transparentweiss[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentDescription[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]DosingQuantity[/COLOR][COLOR=#0000ff]>[/COLOR][B]1.000[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]DosingQuantity[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]DosingUOM[/COLOR][COLOR=#0000ff]>[/COLOR][B]KG[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]DosingUOM[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]DosingUOM_ISO[/COLOR][COLOR=#0000ff]>[/COLOR][B]KGM[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]DosingUOM_ISO[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentReservationNumber[/COLOR][COLOR=#0000ff]>[/COLOR][B]7834543[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentReservationNumber[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentReservationItemNumber[/COLOR][COLOR=#0000ff]>[/COLOR][B]1[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentReservationItemNumber[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentProductionPlant[/COLOR][COLOR=#0000ff]>[/COLOR][B]0003[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentProductionPlant[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentStorageLocation[/COLOR][COLOR=#0000ff]>[/COLOR][B]0003[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentStorageLocation[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentOperation[/COLOR][COLOR=#0000ff]>[/COLOR][B]0010[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentOperation[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentBatchNumberRequired[/COLOR][COLOR=#0000ff]>[/COLOR][B]X[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentBatchNumberRequired[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]</[/COLOR][COLOR=#990000]WorkOrderComponents[/COLOR][COLOR=#0000ff]>[/COLOR]
 
 
[URL="file:///D:/DELETE/a.xml#"][B][FONT=Courier New][COLOR=#ff0000]-[/COLOR][/FONT][/B][/URL] [COLOR=#0000ff]<[/COLOR][COLOR=#990000]WorkOrderComponents[/COLOR][COLOR=#0000ff]>[/COLOR]
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]CurrentWorkOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR][B]9999[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]CurrentWorkOrderItem[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentNumber[/COLOR][COLOR=#0000ff]>[/COLOR][B]58242[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentNumber[/COLOR][COLOR=#0000ff]>[/COLOR] 
 
 [COLOR=#0000ff]<[/COLOR][COLOR=#990000]ComponentDescription[/COLOR][COLOR=#0000ff]>[/COLOR][B]Metalest 26-VF[/B][COLOR=#0000ff]</[/COLOR][COLOR=#990000]ComponentDescription[/COLOR][COLOR=#0000ff]>[/COLOR]

Und zwar möchte ich mir die Componenten Auslesen. Hierfür hab ich folgendes script geschrieben/zusammengefügt.

Code:
Dim i,p
Dim XMLChildnodes
Dim Eintraege
Dim TagElement
Dim XML 
Set XML = CreateObject("MSXML2.DOMDocument")
Dim OpenXML
OpenXML = XML.Load("D:\DELETE\a.xml")
If OpenXML = True Then
Set TagElement = XML.getElementsByTagName("WorkOrderComponents")
    For p = 0 To TagElement.length - 1
        For Each XMLChildnodes In TagElement.Item(p).childNodes
 
'******** Childnodes nacheinander ausgeben **********  
          For Each Eintraege In XMLChildnodes.childNodes
'      ???  MsgBox       'Ausgabe von Werten die in den Klammern stehen <>
      MsgBox (Eintraege.text)   'Ausgabe Textinhalt
    Next
        Next
    Next
Else
    Set XML = Nothing
    Set TagElement = Nothing
        MsgBox "Error: Cannot open XML File:" & vbCrLf & Pfad & vbCrLf & "Check XML-File", vbCritical, "Fatal Error"
    Exit Sub
End If
Set XML = Nothing
Set TagElement = Nothing

nun hab ich das Problem, dass nicht bei dem XML File nicht immer alle childnodes vorhanden sind, sondern ab und zu eines fehlen kann.
nun wollte ich zur sicherheit die Variablenwerte abrufen und vorab prüfen.
Kann mir jemand helfen wie ich zumbeispiel den wert <ComponentNumber> eingelesen bekomme um ihn zu vergleichen?
Vielen dank für die unterstützung.

Denke es fehlt nur der richtige befehl. die Werte kann ich mir ja schon ausgeben lassen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Fehler gefunden

hätte einfach eine ebene höher mit meinen befehlen ansetzten müssen

Code:
'******** Childnodes nacheinander ausgeben **********  
      MsgBox (XMLChildnodes.baseName)      
         For Each Eintraege In XMLChildnodes.childNodes

Danke trotzdem
 
Ich hätte es schön gefunden wenn du nicht den FAQ zugemüllst hättest, sondern
im Ordner HMI einen eigenen Thread eröffnet, mit einen Link auf dem FAQ.

Das wär Elegant gewesen.
 
Zurück
Oben