VS Code XML DOM Management – Part 2

In the previous post, I have published only few set of functions related to XML DOM Management.

Here is a set of additional functions which could be useful when working with XML. It is not fully tested though, In case any issues in the function, please let me know. Hope this helps. Thanks

codeunit 50100 "XML DOM Mgt."
{

procedure AddElement(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text; pNameSpace: Text; var pCreatedNode: XmlNode): Boolean
var
lNewChildNode: XmlNode;
begin
if pNodeText <> '' then
lNewChildNode := XmlElement.Create(pNodeName, pNameSpace, pNodeText).AsXmlNode()
else
lNewChildNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode();
if pXMLNode.AsXmlElement().Add(lNewChildNode) then begin
pCreatedNode := lNewChildNode;
exit(true);
end;
end;

procedure AddRootElement(var pXMLDocument: XmlDocument; pNodeName: Text; var pCreatedNode: XmlNode): Boolean
begin
pCreatedNode := XmlElement.Create(pNodeName).AsXmlNode();
exit(pXMLDocument.Add(pCreatedNode));
end;

procedure AddRootElementWithPrefix(var pXMLDocument: XmlDocument; pNodeName: Text; pPrefix: Text; pNameSpace: text; var pCreatedNode: XmlNode): Boolean
begin
pCreatedNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode();
pCreatedNode.AsXmlElement().Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
exit(pXMLDocument.Add(pCreatedNode));
end;

procedure AddElementWithPrefix(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text; pPrefix: Text; pNameSpace: text; var pCreatedNode: XmlNode): Boolean
var
lNewChildNode: XmlNode;
begin
if pNodeText <> '' then
lNewChildNode := XmlElement.Create(pNodeName, pNameSpace, pNodeText).AsXmlNode()
else
lNewChildNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode();
lNewChildNode.AsXmlElement().Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
if pXMLNode.AsXmlElement().Add(lNewChildNode) then begin
pCreatedNode := lNewChildNode;
exit(true);
end;
end;

procedure AddPrefix(var pXMLNode: XmlNode; pPrefix: Text; pNameSpace: text): Boolean
begin
pXMLNode.AsXmlElement().Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
exit(true);
end;

procedure AddAttribute(var pXMLNode: XmlNode; pName: Text; pValue: Text): Boolean
begin
pXMLNode.AsXmlElement().SetAttribute(pName, pValue);
exit(true);
end;

procedure AddAttributeWithNamespace(var pXMLNode: XmlNode; pName: Text; pNameSpace: text; pValue: Text): Boolean
begin
pXMLNode.AsXmlElement().SetAttribute(pName, pNameSpace, pValue);
exit(true);
end;

procedure FindNode(pXMLRootNode: XmlNode; pNodePath: Text; var pFoundXMLNode: XmlNode): Boolean
begin
exit(pXMLRootNode.SelectSingleNode(pNodePath, pFoundXMLNode));
end;

procedure FindNodeWithNameSpace(pXMLRootNode: XmlNode; pNodePath: Text; pPrefix: Text; pNamespace: Text; var pFoundXMLNode: XmlNode): Boolean
var
lXmlNsMgr: XmlNamespaceManager;
lXMLDocument: XmlDocument;
begin

if pXMLRootNode.IsXmlDocument() then
lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument().NameTable())
else begin
pXMLRootNode.GetDocument(lXMLDocument);
lXmlNsMgr.NameTable(lXMLDocument.NameTable());
end;
lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
exit(pXMLRootNode.SelectSingleNode(pNodePath, lXmlNsMgr, pFoundXMLNode));
end;

procedure FindNodesWithNameSpace(pXMLRootNode: XmlNode; pXPath: Text; pPrefix: Text; pNamespace: Text; var pFoundXmlNodeList: XmlNodeList): Boolean
var
lXmlNsMgr: XmlNamespaceManager;
lXMLDocument: XmlDocument;
begin
if pXMLRootNode.IsXmlDocument() then
lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument().NameTable())
else begin
pXMLRootNode.GetDocument(lXMLDocument);
lXmlNsMgr.NameTable(lXMLDocument.NameTable());
end;
lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
exit(FindNodesWithNamespaceManager(pXMLRootNode, pXPath, lXmlNsMgr, pFoundXmlNodeList));
end;

procedure FindNodesWithNamespaceManager(pXMLRootNode: XmlNode; pXPath: Text; pXmlNsMgr: XmlNamespaceManager; var pFoundXmlNodeList: XmlNodeList): Boolean
begin
if not pXMLRootNode.SelectNodes(pXPath, pXmlNsMgr, pFoundXmlNodeList) then
exit(false);
if pFoundXmlNodeList.Count() = 0 then
exit(false);
exit(true);
end;

procedure FindNodeXML(pXMLRootNode: XmlNode; pNodePath: Text): Text
var
lFoundXMLNode: XmlNode;
begin
if pXMLRootNode.SelectSingleNode(pNodePath, lFoundXMLNode) then
exit(lFoundXMLNode.AsXmlElement().InnerXml());
end;

procedure FindNodeText(pXMLRootNode: XmlNode; pNodePath: Text): Text
var
lFoundXMLNode: XmlNode;
begin
if pXMLRootNode.SelectSingleNode(pNodePath, lFoundXMLNode) then
exit(lFoundXMLNode.AsXmlElement().InnerText());
end;

procedure FindNodeTextWithNameSpace(pXMLRootNode: XmlNode; pNodePath: Text; pPrefix: Text; pNamespace: Text): Text
var
lXmlNsMgr: XmlNamespaceManager;
lXMLDocument: XmlDocument;
begin

if pXMLRootNode.IsXmlDocument() then
lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument().NameTable())
else begin
pXMLRootNode.GetDocument(lXMLDocument);
lXmlNsMgr.NameTable(lXMLDocument.NameTable());
end;
lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
exit(FindNodeTextNs(pXMLRootNode, pNodePath, lXmlNsMgr));
end;

procedure FindNodeTextNs(pXMLRootNode: XmlNode; pNodePath: Text; pXmlNsMgr: XmlNamespaceManager): Text
var
lFoundXMLNode: XmlNode;
begin
if pXMLRootNode.SelectSingleNode(pNodePath, pXmlNsMgr, lFoundXMLNode) then
exit(lFoundXMLNode.AsXmlElement().InnerText());
end;

procedure FindNodes(pXMLRootNode: XmlNode; pNodePath: Text; var pFoundXMLNodeList: XmlNodeList): Boolean
begin
if not pXMLRootNode.SelectNodes(pNodePath, pFoundXmlNodeList) then
exit(false);
if pFoundXmlNodeList.Count() = 0 then
exit(false);
exit(true);
end;

procedure GetRootNode(pXMLDocument: XmlDocument; var pFoundXMLNode: XmlNode): Boolean
var
lXmlElement: XmlElement;
begin
pXMLDocument.GetRoot(lXmlElement);
pFoundXMLNode := lXmlElement.AsXmlNode();
end;

procedure FindAttribute(pXMLNode: XmlNode; var pXmlAttribute: XmlAttribute; pAttributeName: Text): Boolean
begin
exit(pXMLNode.AsXmlElement().Attributes().Get(pAttributeName, pXmlAttribute));
end;

procedure GetAttributeValue(pXMLNode: XmlNode; pAttributeName: Text): Text
var
lXmlAttribute: XmlAttribute;
begin
if pXMLNode.AsXmlElement().Attributes().Get(pAttributeName, lXmlAttribute) then
exit(lXmlAttribute.Value());
end;

procedure AddDeclaration(var pXMLDocument: XmlDocument; pVersion: Text; pEncoding: Text; pStandalone: Text)
var
lXmlDeclaration: XmlDeclaration;
begin
lXmlDeclaration := XmlDeclaration.Create(pVersion, pEncoding, pStandalone);
pXMLDocument.SetDeclaration(lXmlDeclaration);
end;

procedure AddGroupNode(var pXMLNode: XmlNode; pNodeName: Text)
var
lXMLNewChild: XmlNode;
begin
AddElement(pXMLNode, pNodeName, '', '', lXMLNewChild);
pXMLNode := lXMLNewChild;
end;

procedure AddNode(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text)
var
lXMLNewChild: XmlNode;
begin
AddElement(pXMLNode, pNodeName, pNodeText, '', lXMLNewChild);
end;

procedure AddLastNode(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text)
var
lXMLNewChild: XmlNode;
lXMLElement: XmlElement;
begin
AddElement(pXMLNode, pNodeName, pNodeText, '', lXMLNewChild);
if pXMLNode.GetParent(lXMLElement) then
pXMLNode := lXMLElement.AsXmlNode();
end;

procedure AddNameSpace(var pXmlNsMgr: XmlNamespaceManager; pPrefix: text; pNamespace: text);
begin
pXmlNsMgr.AddNamespace(pPrefix, pNamespace);
end;

procedure AddNamespaces(var pXmlNsMgr: XmlNamespaceManager; pXMLDocument: XmlDocument)
var
lXmlAttributeCollection: XmlAttributeCollection;
lXmlAttribute: XmlAttribute;
lXMLElement: XmlElement;
begin
pXmlNsMgr.NameTable(pXMLDocument.NameTable());
pXMLDocument.GetRoot(lXMLElement);
lXmlAttributeCollection := lXMLElement.Attributes();
if lXMLElement.NamespaceUri() <> '' then
pXmlNsMgr.AddNamespace('', lXMLElement.NamespaceUri());
Foreach lXmlAttribute in lXmlAttributeCollection do
if StrPos(lXmlAttribute.Name(), 'xmlns:') = 1 then
pXmlNsMgr.AddNamespace(DelStr(lXmlAttribute.Name(), 1, 6), lXmlAttribute.Value());
end;

procedure XMLEscape(pText: Text): Text
var
lXMLDocument: XmlDocument;
lRootXmlNode: XmlNode;
lXmlNode: XmlNode;
begin
lXMLDocument := XmlDocument.Create();
AddElement(lRootXmlNode, 'XMLEscape', pText, '', lXmlNode);
exit(lXmlNode.AsXmlElement().InnerXml());
end;

procedure LoadXMLDocumentFromText(pXMLText: Text; var pXMLDocument: XmlDocument)
begin
if pXMLText = '' then
exit;
XmlDocument.ReadFrom(pXMLText, pXMLDocument);
end;

procedure LoadXMLNodeFromText(pXMLText: Text; var pXMLNode: XmlNode)
var
lXmlDocument: XmlDocument;
begin
LoadXMLDocumentFromText(pXMLText, lXmlDocument);
pXMLNode := lXmlDocument.AsXmlNode();
end;

procedure LoadXMLDocumentFromInStream(pInStream: InStream; var pXMLDocument: XmlDocument)
begin
XmlDocument.ReadFrom(pInStream, pXMLDocument);
end;

procedure LoadXMLNodeFromInStream(pInStream: InStream; var pXMLNode: XmlNode)
var
lXmlDocument: XmlDocument;
begin
LoadXMLDocumentFromInStream(pInStream, lXmlDocument);
pXMLNode := lXmlDocument.AsXmlNode();
end;

procedure RemoveNamespaces(pXmlText: Text): Text
var
XMLDOMMgt: Codeunit "XML DOM Management";
begin
exit(XMLDOMMgt.RemoveNamespaces(pXmlText));
end;

procedure SetUTF88Declaration(var pXMLDocument: XmlDocument; pStandaloneTxt: Text);
var
lXmlDeclaration: XmlDeclaration;
begin
lXmlDeclaration := XmlDeclaration.Create('1.0', 'utf-8', pStandaloneTxt);
pXMLDocument.SetDeclaration(lXmlDeclaration);
end;

procedure ReplaceInvalidXMLCharacters(pText: Text): Text
var
lText: Text;
begin
lText := pText;
lText := lText.Replace('&', '&amp;');
lText := lText.Replace('<', '&lt;');
lText := lText.Replace('>', '&gt;');
lText := lText.Replace('"', '&quot;');
lText := lText.Replace('''', '&apos;')
exit(lText);
end;

procedure RemoveXMLRestrictedCharacters(pXmlText: Text): Text
var
lXmlText: Text;
lChar: array[30] of Char;
lArrayLen: Integer;
li: Integer;
begin

if pXmlText = '' then
exit(pXmlText);

lXmlText := pXmlText;

lChar[1] := 1;
lChar[2] := 2;
lChar[3] := 3;
lChar[4] := 4;
lChar[5] := 5;
lChar[6] := 6;
lChar[7] := 7;
lChar[8] := 8;
lChar[9] := 11;
lChar[10] := 12;
lChar[11] := 14;
lChar[12] := 15;
lChar[13] := 16;
lChar[14] := 17;
lChar[15] := 18;
lChar[16] := 19;
lChar[17] := 20;
lChar[18] := 21;
lChar[19] := 22;
lChar[20] := 23;
lChar[21] := 24;
lChar[22] := 25;
lChar[23] := 26;
lChar[24] := 27;
lChar[25] := 28;
lChar[26] := 29;
lChar[27] := 30;
lChar[28] := 31;
lChar[29] := 127;

lArrayLen := ArrayLen(lChar);
for li := 1 to lArrayLen do
lXmlText := DelChr(lXmlText, '=', lChar[li]);
exit(lXmlText);
end;
}
Advertisements

9 thoughts on “VS Code XML DOM Management – Part 2

  1. Thank’s Divesh for taking your time with this. It saved me some time!

    I added this to be able to add more namespaces to my root element:

    procedure AddPrefix(var pXMLNode: XmlNode; pPrefix: Text; pNameSpace: text): Boolean
    begin
    pXMLNode.AsXmlElement.Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
    exit(true);
    end;

    Like

  2. Pingback: AL and SOAP | larswestman.se

  3. Pingback: Creating Soap Request Message in AL | Divesh Bora – MSD NAV Blog

  4. Pingback: Creating Soap Request Message in AL - Microsoft Dynamics NAV Community

  5. Hi Divesh,
    I am working on API and wrote code in CAL for accessing each XML tag value. But now I want to write code in AL, but don’t know how to write. Please help me:

    **My XML Content [XmlText] snippet:**

    https://www.mywebsite.com/
    0_YdG/DRSVGCKyy6fx/fdasdY6avs=
    05/28/2019 11:50:14 PM
    0_i1G4fADRTVRDfdsac4GjD5R5UoOPks

    For reference you can look into my previous CAL code:
    **getToken(XmlText : Text) : Text**
    XmlDocument:=XmlDocument.XmlDocument;
    XmlDocument.LoadXml(XmlText);
    XMLNodeList := XmlDocument.GetElementsByTagName(‘Access_Token’);
    count:=XMLNodeList.Count;

    //First for loop to iterate the Access_Token Node– START
    FOR I := 0 TO count – 1 DO BEGIN
    DOMNode := XMLNodeList.Item(I);
    TempXMLNodeList:= DOMNode.ChildNodes;
    childcount:= TempXMLNodeList.Count;
    DOMChildNode:=TempXMLNodeList.Item(I);
    FOR J := 0 TO childcount – 1 DO BEGIN
    DOMChildNode:=TempXMLNodeList.Item(J);
    IF ( FORMAT(DOMChildNode.NodeType)=’Text’ ) OR ( FORMAT(DOMChildNode.NodeType)=’Element’ ) THEN BEGIN
    CurrentElementName:=DOMChildNode.Name;
    IF CurrentElementName = ‘Instance_Url’ THEN BEGIN
    Instance_URL := DOMChildNode.InnerText;
    END
    ELSE IF CurrentElementName = ‘YourToken’ THEN BEGIN
    TOKEN := DOMChildNode.InnerText;
    END
    ELSE IF CurrentElementName = ‘Expiration_date’ THEN BEGIN
    Expiration_date := DOMChildNode.InnerText;
    END
    ELSE IF CurrentElementName = ‘Refresh_Token’ THEN BEGIN
    Refresh_Token := DOMChildNode.InnerText;
    END
    END; // END of major If condition
    END; //Second for loop to iterate the child nodes Access_Token Node — END
    END;//First for loop to iterate the Parent or first node : Access_Token Node — END

    Thanks in Advance.

    Please tell or share code to read XML node values in AL, Most of the Features are not working.

    Like

    • Hi Tabrez,

      Below is the example to read xml in AL as per your requirement.

      codeunit 50101 “Read Xml”
      {
      trigger OnRun()
      var
      lXmlText: Text;
      begin
      lXmlText := ”;
      lXmlText += ”;
      lXmlText += ‘URl1’;
      lXmlText += ”;
      lXmlText += ‘TOKEN 1’;
      lXmlText += ”;
      lXmlText += ”;

      lXmlText += ”;
      lXmlText += ‘URl2’;
      lXmlText += ”;
      lXmlText += ‘TOKEN 2’;
      lXmlText += ”;
      lXmlText += ”;

      lXmlText += ”;
      lXmlText += ‘URL21’;
      lXmlText += ”;
      lXmlText += ‘TOKEN 21’;
      lXmlText += ”;
      lXmlText += ”;

      lXmlText += ”;
      ReadXml(lXmlText);
      end;

      local procedure ReadXml(pXmlText: Text);
      var
      XmlDOMMgt: Codeunit “XML DOM Mgt.”;
      lXmlDocument: XmlDocument;
      lXmlRootNode: XmlNode;
      lAccessTokenList: XmlNodeList;
      lNodeList: XmlNodeList;
      lXMLNode: XmlNode;
      lTempNode: XmlNode;
      begin
      XmlDOMMgt.LoadXMLDocumentFromText(pXmlText, lXmlDocument);
      XmlDOMMgt.GetRootNode(lXmlDocument, lXmlRootNode);
      if not XmlDOMMgt.FindNodes(lXmlRootNode, ‘Access_Token’, lAccessTokenList) then
      error(‘Node Access_Token not found’);
      foreach lXMLNode in lAccessTokenList do begin
      lNodeList := lXMLNode.AsXmlElement().GetChildNodes();
      foreach lTempNode in lNodeList do
      case lTempNode.AsXmlElement().Name() of
      ‘Instance_Url’:
      Message(lTempNode.AsXmlElement().InnerText());
      ‘YourToken’:
      Message(lTempNode.AsXmlElement().InnerText());
      end;
      end;
      end;
      }

      Hope this helps. Please like and share the post if you think it helped. Thanks

      Like

  6. Hi Divesh,

    We need to write the code in AL to load the xml file saved on server. In CAL the Code is like :
    procedure ReadPackageHeader(DecompressedFileName: Text)
    var
    XMLDOMManagement: Codeunit “XML DOM Management”;
    PackageXML: DotNet XmlDocument;
    begin
    if “Package File Name” ” then begin
    XMLDOMManagement.LoadXMLDocumentFromFile(DecompressedFileName,PackageXML);
    ReadPackageHeaderCommon(PackageXML);
    end else begin
    “Package Code” := ”;
    “Package Name” := ”;
    “Product Version” := ”;
    “Language ID” := 0;
    end;
    end;
    local procedure ReadPackageHeaderCommon(PackageXML: DotNet XmlDocument)
    var
    ConfigPackage: Record “Config. Package”;
    ConfigXMLExchange: Codeunit “Config. XML Exchange”;
    DocumentElement: DotNet XmlElement;
    LanguageID: Text;
    begin
    DocumentElement := PackageXML.DocumentElement;
    “Package Code” :=
    CopyStr(
    ConfigXMLExchange.GetAttribute(
    ConfigXMLExchange.GetElementName(ConfigPackage.FieldName(Code)),DocumentElement),
    1,MaxStrLen(“Package Code”));
    if “Package Code” = ” then
    Error(PackageDataNotDefinedErr,FieldCaption(“Package Code”));
    “Package Name” :=
    CopyStr(
    ConfigXMLExchange.GetAttribute(
    ConfigXMLExchange.GetElementName(ConfigPackage.FieldName(“Package Name”)),DocumentElement),
    1,MaxStrLen(“Package Name”));
    if “Package Name” = ” then
    Error(PackageDataNotDefinedErr,FieldCaption(“Package Name”));
    “Product Version” :=
    CopyStr(
    ConfigXMLExchange.GetAttribute(
    ConfigXMLExchange.GetElementName(ConfigPackage.FieldName(“Product Version”)),DocumentElement),
    1,MaxStrLen(“Product Version”));
    LanguageID := ConfigXMLExchange.GetAttribute(
    ConfigXMLExchange.GetElementName(ConfigPackage.FieldName(“Language ID”)),DocumentElement);
    if LanguageID ” then
    Evaluate(“Language ID”,LanguageID);
    Modify;
    end;
    I have tried the XmlDocument.ReadFrom but it is only useful when i have the xml in text variable. May i know to how we can load the xml files in AL programming.
    Thanks in Advance.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s