Verarbeitung eines XML Dokumentes in NAV

Wie kann ein XML Dokument in Microsoft Dynamics NAV mit Hilfe von MSXML DOM eingelesen werden:

1. Erstellen Sie eine neue Codeunit.

2. Deklarieren Sie die folgenden fünf globalen Variablen:

XMLDoc Type = Automation 'Microsoft XML, v4.0'.DOMDocument
DOMNode Type = Automation 'Microsoft XML, v4.0'.IXMLDOMNode
XMLNodeList Type = Automation 'Microsoft XML, v4.0'.IXMLDOMNodeList
CurrentElementName Type = Text 30
i Type = Integer

In diesem Beispiel habe ich die MSXML Version 4 verwendet. Sie können natürlich auch jede andere MSXML Version verwenden wie z.B. 5 oder 6. Meistens wird die Version 4 verwendet, da dort alle benötigten Methoden beinhaltet sind und Abwärtskompatibel zu den älteren Versionen ist.

3. Initialisieren Sie das MSXML Dom Dokument:
CREATE(XMLDoc);
XMLDoc.async(FALSE);
XMLDoc.load('C:\XML\MyXML.xml');

Die Methode asynch = False sorgt dafür, das ein Dokument komplett eingelesen wird.

Wenn es keine speziellen Gründe gibt, die dagegen sprechen das Dokument ganz in den Speicher einzulesen sollten Sie diese Methode verwenden.

Das gilt primär für den Fall, dass Sie ein Dokument in NAV einlesen. Mit dieser Methode stellen Sie sicher, dass das komplette XML Dokument in den Speicher gelesen wird, bevor Sie es weiterverarbeiten. Wenn diese Methode nicht verwenden, kann es sein das Sie das Dokument verarbeiten, bevor es komplett eingelesen wurde.

4. Richten Sie eine Schleife ein um die einzelnen Knoten des Dokuments zu durchsuchen:
XMLNodeList := XMLDoc.childNodes;
for i := 0 to XMLNodeList.length - 1 do begin
DOMNode := XMLNodeList.item(i);
ReadChildNodes(DOMNode);
end;

Sie können auch eine eigene Funktion mit einem Parameter schreiben, z.B. ReadChildNodes:
CurrentXMLNode, Type = Automation 'Microsoft XML, v4.0'.IXMLDOMNode.

Der Grund für die Funktion ist es einen rekursiven Funktionsaufruf zu gewährleisten. Das ist in diesem Sinnvoll da Sie nicht wissen können wie viele Unterknoten (Child Nodes) das Dokument besitzt.

Erstellen Sie die Funktion ReadChildNodes.

Die Funktion hat einen Parameter:
CurrentXMLNode : Automation "'Microsoft XML, v4.0'.IXMLDOMNode"

Fügen Sie die folgenden lokalen Variablen hinzu.
TempXMLNodeList Automation = 'Microsoft XML, v4.0'.IXMLDOMNodeList
TempXMLAttributeList Automation = 'Microsoft XML, v4.0'.IXMLDOMNamedNodeMap
j Integer
k Integer

Diese Funktion überprüft den Datentypen des Knotens. Ein Knoten kann ein Element sein oder ein Text (Data) oder ein Attribut sein. Eigenschaft .nodeType beschreibt den Datentyp des Knotens. Alle Typen werden ausführlich im MSXMLSDK beschrieben.

Das ist die Funktion:
ReadChildNodes(CurrentXMLNode : Automation "'Microsoft XML, v4.0'.IXMLDOMNode")

CASE FORMAT(CurrentXMLNode.nodeType) OF

'1': // Element
BEGIN
// Globale Variable CurrentElementName behält den zu bearbeitenden Knoten im Fokus.
CurrentElementName := CurrentXMLNode.nodeName;

    // Verarbeitung von Attributen
// Wenn ein Element Attribute besitzt, lese wir diese aus.
TempXMLAttributeList := CurrentXMLNode.attributes;
FOR k := 0 TO TempXMLAttributeList.length - 1 DO
ReadChildNodes(TempXMLAttributeList.item(k));

    // Verarbeitung der “Child nodes”
TempXMLNodeList := CurrentXMLNode.childNodes;
FOR j := 0 TO TempXMLNodeList.length - 1 DO
ReadChildNodes(TempXMLNodeList.item(j));
END;

'2': //Attribute
BEGIN
MESSAGE(CurrentElementName + ' Attribute : ' +
FORMAT(CurrentXMLNode.nodeName) + ' = ' + FORMAT(CurrentXMLNode.nodeValue));
END;

'3': //Text
BEGIN
MESSAGE(CurrentElementName + ' = ' + FORMAT(CurrentXMLNode.nodeValue));
END;
END;

Versuchen Sie jetzt die Codeunit gegen ein XML Dokument zu starten. Es sollten Ihnen für jeden Knoten und jedes Attribut eine MESSAGE ausgegeben werden. Diese Codeunit kann dazu benutzt werden die Struktur eines XML Dokumentes in NAV zu untersuchen und auszulesen.

Nächstes Beispiel:

Gehen wir einmal davon aus, Sie suchen nach einem speziellen Knoten in dem XML Dokument:

Beispiel XML Dokument:

 - <Document>
   - <Order ID="1001">
     - <Line>
       10000
       <No>70000</No>
       <Amount>77</Amount>
     </Line>
     - <Line>
       20000
       <No>70001</No>
       <Amount>99</Amount>
     </Line>
   </Order>
   - <Order ID="1002">
     - <Line>
       10000
       <No>70011</No>
       <Amount>12</Amount>
     </Line>
     - <Line>
       20000
       <No>70012</No>
       <Amount>45</Amount>
     </Line>
     - <Line>
       30000
       <No>70014</No>
       <Amount>37</Amount>
     </Line>
   </Order>
 </Document>

 

Eines der Vorzüge von MSXML ist es, dass wir die Möglichkeit haben das ganze XML Dokument in den Speicher zu lesen. Das ermöglicht uns, zwischen den einzelnen Knoten hin und herzu springen oder das komplette Dokument zu untersuchen.

Ziehen wir nun das oben aufgeführte XML Dokument als Beispiel heran. Als erstes zählen wir wie viele Aufträge in dem Dokument enthalten sind. Als Schlüsselwort nehmen wir das Wort Order aus den Knoten.

OnRun()
CREATE(XMLDoc);
XMLDoc.async(FALSE);
XMLDoc.load('C:\XML\Order.xml');

:= XMLDoc.getElementsByTagName('Document/Order');
MESSAGE(Das Dokument besitzt %1 Elemente mit Namen Order',XMLNodeList.length);

Die Methode “getElementsByTagName” gibt uns alle Elemente zu einem speziellen Namen zurück. Achten Sie bitte darauf das XML „Case sensitive“ ist, d.h das genau auf Groß- und Kleinschreibung geachtet werden muss.

Abschließend noch ein kurzes Beispiel, wie das das obige Beispiel XML Dokument eingelesen werden kann und die Gesamtmenge der Aufträge ausgegeben werden kann.

OnRun()
CREATE(XMLDoc);
XMLDoc.async(FALSE);
XMLDoc.load('C:\XML\Order.xml');

XMLNodeList := XMLDoc.getElementsByTagName('Document/Order');
FOR i := 0 TO XMLNodeList.length - 1 DO BEGIN
NumberDecTotal := 0;
DOMNode := XMLNodeList.item(i);
XMLNodeList2 := DOMNode.selectNodes('Line/Amount');
FOR j := 0 TO XMLNodeList2.length - 1 DO BEGIN
DOMNode2 := XMLNodeList2.item(j);
NumberAsText := FORMAT(DOMNode2.text);
EVALUATE(NumberDec,NumberAsText);
NumberDecTotal := NumberDecTotal + NumberDec;
END;
MESSAGE('Order has total amount of %1.',NumberDecTotal);
END;

In dem Beispiel-Code verwenden wir die Methode DomNode.SelectNodes. Diese Methode markiert alle gleichen Knoten eines Begriffes. Wenn Sie nach individuellen Knoten suchen möchten können Sie die Methode DomNode.SelectNodes verwenden.

Dieses XML Beispiel besteht nur aus Text. Um das Dokument in NAV richtig verarbeiten zu können, achten Sie bitte darauf das Sie evtl. Zahlen richtig konvertieren müssen.

Achten Sie bitte darauf, dass Sie Ihren produktiven Code mit einer Fehlerbehandlung ausstatten, damit meine ich das evtl. ein Amount Feld doch auch ein Buchstaben beinhalten kann. Das kann in NAV zu späteren Fehler führen.

Dieser Artikel wurde zuerst veröffentlicht unter "Sample of how to read a simple XML document using MSXML DOM in NAV"

These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use.

Mit freundlichen Grüßen

Sebastian Röttel

Microsoft Dynamics Germany

Microsoft Customer Service and Support (CSS) EMEA