mandag den 2. april 2012

Copy one xml document into another xml document

XMLnode := XmlDoc.selectSingleNode('element/node');

DocFragment := XmlRequest.createDocumentFragment();
DocFragment.appendChild(NewDocument.documentElement);

XMLnode.appendChild(DocFragment);

mandag den 12. marts 2012

Tracking Usage with Google Analytics

utm_url := utm_location + '?' +
'utmwv=' + Version +
'&utmn=' + random_number +
'&utmhn=' + 'loggersite.com' +
'&utmr=' + 'user' +
'&utmp=' + UrlEncode('/', '%2F') +
'&utmac=' + 'macid' +
'&utmcc=__utma%3D999.999.999.999.999.1%3B' +
'&utmvid=' + 'VisitorId';

onsdag den 11. januar 2012

Connecting to REST WebService from Navision

I will let the code speak for itself:

Complete CodeUnit:

 OBJECT Codeunit 90002 WebService Connection  
 {  
  OBJECT-PROPERTIES  
  {  
   Date=11-01-12;  
   Time=15:05:21;  
   Modified=Yes;  
   Version List=;  
  }  
  PROPERTIES  
  {  
   OnRun=BEGIN  
       CREATE(XmlIn);  
       CREATE(XmlOut);  
       // Populating XmlIn document for test purposes  
       LoadTestXml();  
       // Invoke method  
       Send();  
       // Save result to disc  
       XmlOut.save('C:\Temp\XML\response.xml');  
      END;  
  }  
  CODE  
  {  
   VAR  
    XmlIn@1000000004 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    XmlOut@1000000003 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    locautXmlHttp@1160870000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{88D96A0A-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v6.0'.XMLHTTP60";  
   PROCEDURE Send@1000000004();  
   BEGIN  
    // Communication  
    CREATE(locautXmlHttp);  
    locautXmlHttp.open('POST','http://localhost:56063/RESTservice.ashx',0);  
    locautXmlHttp.setRequestHeader('Content-type','text/xml; charset=utf-8');  
    locautXmlHttp.setRequestHeader('KeepAlive','false');  
    locautXmlHttp.setRequestHeader('Timeout','5000');  
    // Send request  
    locautXmlHttp.send(XmlIn);  
    // Get response  
    XmlOut := locautXmlHttp.responseXML;  
    XmlOut.async := TRUE;  
    // Show result  
    MESSAGE(XmlOut.xml);  
   END;  
   PROCEDURE LoadTestXml@1160870000();  
   BEGIN  
    XmlIn.loadXML(  
    '<xmltest>' +  
    '<test>' +  
    'This document can contain anything. But must not contain xml decleration.' +  
    '</test>' +  
    '</xmltest>');  
   END;  
   BEGIN  
   {  
    Shows how to connect to a REST Web Service  
   }  
   END.  
  }  
 }  


.NET REST webservice implemented as a generic handler (.ashx) nothing fancy:

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Web;  
 using System.Text;  
 namespace WebServiceApplication  
 {  
   /// <summary>  
   /// Summary description for RESTservice  
   /// </summary>  
   public class RESTservice : IHttpHandler  
   {  
     public void ProcessRequest(HttpContext context)  
     {  
       string requestMethod = context.Request.HttpMethod; // POST, PUT, GET or DELETE  
       System.Xml.XmlDocument doc = new System.Xml.XmlDocument();  
       doc.Load(context.Request.InputStream);  
       System.IO.Stream stream = context.Request.InputStream;  
       byte[] bytes = new byte[stream.Length];  
       stream.Position = 0; // Resetting reading position  
       stream.Read(bytes, 0, (int)stream.Length);  
       string data = Encoding.ASCII.GetString(bytes); // this is your string  
       //context.Response.ContentType = "text/plain";  
       context.Response.ContentType = "text/xml";  
       context.Response.Write("<result>Hello World</result>");  
       context.Response.End();  
     }  
     public bool IsReusable  
     {  
       get  
       {  
         return false;  
       }  
     }  
   }  
 }  

mandag den 9. januar 2012

Validating xml with a schema

A XML Schema is a contract on how the XML structure should look. In a data transmission both parts know how the XML document should/could look.

XML Schemas can only be used with XMLDocument60 previous versions only support DTD.

Implicit validation:
 doc.validateOnParse := true;  

Explicit validation:
 doc.validate();  

Complete CodeUnit examble:

 OBJECT Codeunit 90003 SchemaValidation  
 {  
  OBJECT-PROPERTIES  
  {  
   Date=09-01-12;  
   Time=15:22:39;  
   Modified=Yes;  
   Version List=;  
  }  
  PROPERTIES  
  {  
   OnRun=BEGIN  
       ImplicitValidate();  
       ExplicitValidate();  
      END;  
  }  
  CODE  
  {  
   VAR  
    XmlDocument@1160870000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{88D96A05-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v6.0'.DOMDocument60";  
    XmlSchema@1160870001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{88D96A05-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v6.0'.DOMDocument60";  
   PROCEDURE ImplicitValidate@1160870001();  
   VAR  
    XmlSchemaCache@1160870000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{88D96A07-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v6.0'.XMLSchemaCache60";  
   BEGIN  
    CLEAR(XmlDocument);  
    CLEAR(XmlSchemaCache);  
    CREATE(XmlSchemaCache);  
    CREATE(XmlDocument);  
    XmlDocument.async := FALSE;  
    // Populating Schema  
    LoadSchema();  
    // Apply schema to schemacache with namespace. '' apply to default namespace  
    XmlSchemaCache.add('', XmlSchema);  
    // apply schema to xmldocument  
    XmlDocument.schemas := XmlSchemaCache;  
    // validate data when loading of XML is finished  
    XmlDocument.validateOnParse := TRUE;  
    // loading xml into document. XML is parsed when loading is done and false is returned if schema validation failed  
    IF LoadXmlDocument() THEN BEGIN  
     MESSAGE('VALID IMPLICIT');  
    END  
    ELSE BEGIN  
     MESSAGE('ERROR IMPLICIT');  
    END;  
    // loading xml into document. XML is parsed when loading is done and false is returned if schema validation failed  
    IF LoadXmlDocumentWithError() THEN BEGIN  
     MESSAGE('VALID IMPLICIT');  
    END  
    ELSE BEGIN  
     MESSAGE('ERROR IMPLICIT');  
    END;  
   END;  
   PROCEDURE ExplicitValidate@1160870005();  
   VAR  
    XmlSchemaCache@1160870000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{88D96A07-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v6.0'.XMLSchemaCache60";  
    XmlParseError@1160870001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{3EFAA428-272F-11D2-836F-0000F87A7782}:'Microsoft XML, v6.0'.IXMLDOMParseError2";  
   BEGIN  
    CLEAR(XmlDocument);  
    CLEAR(XmlSchemaCache);  
    CREATE(XmlSchemaCache);  
    CREATE(XmlDocument);  
    XmlDocument.async := FALSE;  
    // Populating Schema  
    LoadSchema();  
    // Apply schema to schemacache with namespace. '' apply to default namespace  
    XmlSchemaCache.add('', XmlSchema);  
    // apply schema to xmldocument  
    XmlDocument.schemas := XmlSchemaCache;  
    // validate data when loading of XML is finished  
    XmlDocument.validateOnParse := FALSE;  
    // loading xml into document. XML is not parsed when loading is done and true is returned unless the XML convension is not complied  
    LoadXmlDocument();  
    // XML content is validated against the schema and a validation result object is returned.  
    XmlParseError := XmlDocument.validate();  
    // If errorCode is 0 then there was no errors in the validation  
    IF XmlParseError.errorCode = 0 THEN  
    BEGIN  
     MESSAGE('VALID EXPLICIT');  
    END  
    ELSE BEGIN  
     MESSAGE('ERROR EXPLICIT: ' + XmlParseError.reason + ' - ' + XmlParseError.srcText + ' - ' + FORMAT(XmlParseError.line));  
    END;  
    // loading xml into document. XML is not parsed when loading is done and true is returned unless the XML convension is not complied  
    LoadXmlDocumentWithError();  
    // XML content is validated against the schema and a validation result object is returned.  
    XmlParseError := XmlDocument.validate();  
    // If errorCode is 0 then there was no errors in the validation  
    IF XmlParseError.errorCode = 0 THEN  
    BEGIN  
     MESSAGE('VALID EXPLICIT');  
    END  
    ELSE BEGIN  
     MESSAGE('ERROR EXPLICIT: ' + XmlParseError.reason + ' - ' + XmlParseError.srcText + ' - ' + FORMAT(XmlParseError.line));  
    END;  
   END;  
   PROCEDURE LoadSchema@1160870002();  
   BEGIN  
    CLEAR(XmlSchema);  
    CREATE(XmlSchema);  
    XmlSchema.async := FALSE;  
    XmlSchema.loadXML(  
    '<?xml version="1.0" encoding="utf-8" ?>' +  
    '<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">' +  
     '<xs:element name="xmltest">' +  
      '<xs:complexType>' +  
       '<xs:sequence>' +  
        '<xs:element name="elem1">' +  
         '<xs:complexType>' +  
          '<xs:sequence>' +  
           '<xs:element name="elem2" type="xs:string" minOccurs="1" />' +  
           '<xs:element name="elem3" type="xs:unsignedByte" />' +  
           '<xs:element name="elem4" type="xs:decimal" />' +  
          '</xs:sequence>' +  
         '</xs:complexType>' +  
        '</xs:element>' +  
       '</xs:sequence>' +  
      '</xs:complexType>' +  
     '</xs:element>' +  
    '</xs:schema>');  
   END;  
   PROCEDURE LoadXmlDocument@1160870003() LoadSuccess : Boolean;  
   BEGIN  
    LoadSuccess := XmlDocument.loadXML(  
    '<?xml version="1.0" encoding="utf-8" ?>' +  
    '<xmltest>' +  
     '<elem1>' +  
      '<elem2>v‘rdi</elem2>' +  
      '<elem3>3</elem3>' +  
      '<elem4>1.5</elem4>' +  
     '</elem1>' +  
    '</xmltest>');  
   END;  
   PROCEDURE LoadXmlDocumentWithError@1160870004() LoadSuccess : Boolean;  
   BEGIN  
    LoadSuccess := XmlDocument.loadXML(  
    '<?xml version="1.0" encoding="utf-8" ?>' +  
    '<xmltest>' +  
     '<elem1>' +  
    //  '<elem2>v‘rdi</elem2>' + // This makes an error <xs:element name="elem2" type="xs:string" minOccurs="1" />  
      '<elem3>3</elem3>' +  
      '<elem4>1.5</elem4>' +  
     '</elem1>' +  
    '</xmltest>');  
   END;  
   BEGIN  
   {  
    Shows how to validate XML using a XML-Schema  
   }  
   END.  
  }  
 }  

mandag den 2. januar 2012

Getting XML Dom parse error in Navision

 // Getting the Exception Message  
 ERROR(locautXmlDoc.parseError.reason);  
 // Getting the Code producing the error  
 ERROR(locautXmlDoc.parseError.srcText);  

Connecting to SOAP WebService from Navision

Connect to a Soap Web Service using the XMLHttp contained in the Microsoft XML Automation.
Version 2. View version list at the bottom.

    // Communication  
    CREATE(locautXmlHttp);  
    locautXmlHttp.open('POST','http://localhost:56063/SoapService.asmx',0);  
    locautXmlHttp.setRequestHeader('Content-type','application/soap+xml; charset=utf-8');  
    locautXmlHttp.setRequestHeader('SOAPAction','http://tempuri.org/NavisionRequest');  
    locautXmlHttp.send(locautXmlDoc);  
    locautXmlDoc := locautXmlHttp.responseXML;  
    locautXmlDoc.async := TRUE;  

Complete CodeUnit;

 OBJECT Codeunit 90002 WebService Connection  
 {  
  OBJECT-PROPERTIES  
  {  
   Date=02-01-12;  
   Time=20:21:46;  
   Modified=Yes;  
   Version List=;  
  }  
  PROPERTIES  
  {  
   OnRun=BEGIN  
       CREATE(XmlIn);  
       CREATE(XmlOut);  
       // Populating XmlIn document for test purposes  
       LoadTestXml();  
       // Invoke method  
       Send(XmlIn, XmlOut, 'User', 'Pass');  
       // Save result to disc  
       XmlOut.save('C:\Temp\XML\response.xml');  
      END;  
  }  
  CODE  
  {  
   VAR  
    XmlIn@1000000004 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    XmlOut@1000000003 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    DecodeXSLT@1000000008 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    locautXmlDoc@1000000010 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";  
    ResultNode@1000000011 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";  
   PROCEDURE Send@1000000004(XmlRequest@1000000002 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";VAR XmlReply@1000000003 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";User@1000000005 : Text[30];Password@1000000006 : Text[30]);  
   VAR  
    locautXmlHttp@1000000000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F16-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.XMLHTTP";  
    bodyXMLnode@1000000004 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";  
   BEGIN  
    CLEAR(XmlReply);  
    CREATE(XmlReply);  
    // Load Soap Envelope  
    LoadSendEnvelope(User,Password);;  
    // Load Transformation schema for URL-decode  
    LoadDecodeXlsSchema;  
    bodyXMLnode := locautXmlDoc.selectSingleNode('soap:Envelope/soap:Body/NavisionRequest/request');  
    // Inserting xml into text property it gets URL-encodes automatic  
    bodyXMLnode.text := XmlRequest.xml;  
    // Communication  
    CREATE(locautXmlHttp);  
    locautXmlHttp.open('POST','http://localhost:56063/SoapService.asmx',0);  
    locautXmlHttp.setRequestHeader('Content-type','application/soap+xml; charset=utf-8');  
    locautXmlHttp.setRequestHeader('SOAPAction','http://tempuri.org/NavisionRequest');  
    locautXmlHttp.send(locautXmlDoc);  
    locautXmlDoc := locautXmlHttp.responseXML;  
    locautXmlDoc.async := TRUE;  
    // Readin reply  
    XmlReply := locautXmlDoc;  
    // Fetching response  
    ResultNode := locautXmlDoc.selectSingleNode('soap:Envelope/soap:Body/NavisionRequestResponse/NavisionRequestResult');  
    // Parsing response 
    ResultNode.transformNodeToObject(DecodeXSLT, XmlReply);  
   END;  
   PROCEDURE LoadDecodeXlsSchema@1000000002();  
   BEGIN  
    CREATE(DecodeXSLT);  
    DecodeXSLT.loadXML(  
    '<?xml version="1.0" encoding="UTF-8" ?>' +  
    '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' +  
    '<xsl:output indent="yes" />' +  
    '<xsl:template match="*"> ' +  
    //'<xsl:element name="{local-name()}">' +  
    '<xsl:value-of select="." disable-output-escaping="yes"></xsl:value-of>' +  
    //'</xsl:element>' +  
    '</xsl:template>' +  
    '</xsl:stylesheet>');  
   END;  
   PROCEDURE LoadSendEnvelope@1000000006(parUser@1000000001 : Text[30];parPassword@1000000000 : Text[30]);  
   BEGIN  
    CREATE(locautXmlDoc);  
    locautXmlDoc.async := FALSE;  
    locautXmlDoc.loadXML(  
    '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +  
    '<soap:Body>' +  
    '<NavisionRequest xmlns="http://tempuri.org/">' +  
    '<username>'+parUser+'</username>' +  
    '<password>'+parPassword+'</password>' +  
    '<request><xmltest><value>test</value></xmltest></request>' +  
    '</NavisionRequest>' +  
    '</soap:Body>' +  
    '</soap:Envelope>');  
   END;  
   PROCEDURE LoadTestXml@1160870000();  
   BEGIN  
    XmlIn.loadXML(  
    '<xmltest>' +  
    '<test>' +  
    'This document can contain anything. But must not contain xml decleration.' +  
    '</test>' +  
    '</xmltest>');  
   END;  
   BEGIN  
   {  
    Shows how to connect to a SOAP Web Service.
    Version 2. For change history view:
       http://navcode.blogspot.com/2012/01/connecting-to-soap-webservice-from.html  
   }  
   END.  
  }  
 }  


Code examble of the .Net webservice:

 using System;  
 using System.Web;  
 using System.Web.Services;  
 namespace WebServiceApplication  
 {  
   /// <summary>  
   /// Web Service for Navision Integration purpose  
   /// </summary>  
   [WebService(Namespace = "http://tempuri.org/")]  
   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
   [System.ComponentModel.ToolboxItem(false)]  
   public class SoapService : System.Web.Services.WebService  
   {  
     [WebMethod]  
     public string HelloNavision()  
     {  
       return "Hello Navision";  
     }  
     [WebMethod]  
     public string NavisionRequest(string username, string password, string request)  
     {  
       if (string.IsNullOrEmpty(request))  
       {  
         return "Tinfoilhat!";  
       }  
       System.Xml.XmlDocument resp = new System.Xml.XmlDocument();  
       resp.LoadXml(request);  
       return resp.OuterXml;  
     }  
     [WebMethod]  
     public void ParamTest(System.Xml.XmlDocument xmldoc)  
     {  
     }  
   }  
 }  


Version List:
1. Init
2. Bufferoverflow error fixed:
XmlReply.loadXML(ResultNode.transformNode(DecodeXSLT)); was changed to
ResultNode.transformNodeToObject(DecodeXSLT, XmlReply); due to the loadXML uses the Navision
string buffer as temporary container for the decoded XML this means 1024 chars.

fredag den 16. december 2011

HTML Encode using the XMl DOM Automation

NAV Code:

 CREATE(XMLDoc);  
 XMLDoc.load(XmlToBeEncoded);  
 IXMLDOMText := XMLDoc.createTextNode(XMLDoc.xml);  
 EncodedXml := IXMLDOMText