• Internet
  • 09.10.2018
  • EN

Manuel Schnitger: RQL in a nutshell - Part II

written by Manuel Schnitger, 26. January 2011

Even after studying this fascinating article (RQL in a nutshell) of a brilliant developer and talented writer ;) you’ll soon have questions which are not answered in the formerly mentioned article. Therefore I write down some hints that might help you when creating RQL-based applications.


Event controlled RQL

Normally an RQL plugin is called via a link in SmartEdit or SmartTree and will be executed in the second you click on the link…..so user interaction is required.  But what has to be done if you want the plugin/application to be executed when a specific event (e.g.: page released) in the workflow is reached? Let’s  do it step-by-step.

In this sample the goal is that you trigger an RQL application via the workflow. The action that is performed is not important….just the steps that result into performing the action.


Step #1: Creating a user defined job in the Server Manager

  1. Go to the Server Manager > User defined jobs and click on “Create user defined job” in the action menu

Figure 1:Server Manager - Administer user defined jobs

  1. in the upcoming dialogue enter a name for this job (e.g.: myNewJob)

Figure #2: Add a name for the job

  1. in the next dialogue activate the checkbox “call event controlled” and deactivate the other one (important!)

Figure 3: Activating the option "Event controlled"

  1. in the next dialogue choose the option “Open URL” and enter the url to your RQL application

Figure 4: Adding the URL of your application


Step #2) Assigning the user defined job in the project

  1. Enter the SmartTree
  2. create a workflow
  3. click on “Page released” and then on “add reaction”  (of course jobs can not just being triggered when the workflow level is “page released” ;-))

Figure 5: Small sample workflow

  1. In the opening dialogue click on “Start job” and choose the user defined job you just created in the Server Manager.

Figure 6: Workflow triggers a user defined job (RQL application)

Ready!!! Now the RQL application will be triggerred each time a page that is connected to this specific list is being released.

Normally when you wish to start a job when a specific step in the workflow is reached you also want to let the RQL application do something with the page in workflow. But how do you know the GUID of the page in the workflow? And how can you transfer the GUID of the page into your application? It’s very simple. Just add another reaction to the workflow! Click on the action “page released”  then on “add reation” in the action menu and choose the reaction “Write workflow XML“. You’ll be asked for a location (folder) where the workflow xml file(s) shall be placed (see figure below) after closing the dialogue every time a page is released two things happen. First the workflow xml file will be written (one file for each page & event) under the specified path and after that the RQL application is triggered. What you then have to do in your application is: Reading out the page guid and using it in your application.

Figure 7: Path for the workflow xml files

Sample code how to extract the GUID of a page and the GUID of the project the page is part of:

Set oXml = Server.CreateObject("Microsoft.XMLDOM")
Set rootNode = oXml.documentElement
if rootNode.hasChildNodes() Then
  for Each e in rootNode.childNodes
    if e.nodename = "PAGEGUID" then
      sPageGuid = e.childNodes(0).text
      response.write "<br>PageGuid: " & sPageGuid & "<br>"
    end if
    if e.nodename = "PROJECTGUID" then
      sProjectGuid = e.childNodes(0).text
      response.write "<br>ProjectGuid: " & sProjectGuid & "<br>"
    end if
end if

Please be aware of the fact that -if you call an RQL application this way- you don’t have any session variables such as login guid or the session key. So you’ll have to write some RQL code for the login procedure and the validation (= connecting to a project). (If you should face issues with these steps… leave a comment.)



If you want to delete something using RQL you write something like <PAGE action=”delete” or <USER action=”delete” or something similar depending on the thing you wish to delete. This works well whenever you want to delete the “object” itself; it does not work when you’d like to delete the content (Text) of an object (Textelement).  In order to delete a text from a text element or from  a standardfield you have to save the so called “Empty buffer”. (Of course the empty buffer can delete much more than just the content of a text element or standardfield.)

Sample for deleting the text of a text element:

sValue = session("EmptyBuffer")
"<IODATA format=""1"" loginguid=""" & sLoginGUID & """ sessionkey=""" & sSessionKey & """>"&_
"<ELT reddotcacheguid="""" action=""save"" guid=""" & sEltGuid & """ pageid="""" id="""" index="""" type=""" & sType & """>" & sValue & "</ELT>"&_

Q: What is the empty buffer?
A: It’s just a hash tag followed by the session key of the current user.
So this: response.write session(“emptybuffer”) and this: response.write “#” & session(sessionkey) result in the same output.


Remote RQL

Generally plugins or other RQL based applications are placed on the editorial server meaning the server where the Open Text Management Server software is installed. And normally plugins are called via a link or RQL applications are triggered by the workflow. But what if you have a server where a specific application runs and when you want to execute RQL statements triggered by this application?

Sample: There is an application that writes product related information into an XML file and you want to create a page on the editorial server based on this information.

What you could do is a) writing a small directory listener that notices when a new file is being written b) read out the relevant data and c) use the RQL bridge to communicate with the editorial server.

Ok, let’s do it step-by-step


Step #1) Create a file called “RqlBridge. asp” using this code and place it in a folder called “remoterql” under the plugins directory (obviously you have to create this folder ;) on the editorial server.

<%@ Language = VBScript %>
<%server.ScriptTimeout = 5 %>
  function sendXML(XMLString)
    set objData = server.CreateObject("RDCMSASP.RdPageData")
    objData.XmlServerClassName = "RDCMSServer.XmlServer"
    sendXML = objData.ServerExecuteXml(XMLString, sErrors)
  end function
  XMLString = request("sXmlData")
  if XMLString <> "" then
    sReturn = sendXML(XMLString)
    Response.Write sReturn
  end if

As we can see, the function sendXML just executes the RQL statement. The function itself is called in the second block of the code. In the code below we then can see how the communication between the editorial server and the “other” server is managed.


Step #2:  Create a file based on this code and place it on the “other” server.

As I write some information in the code you will not be able to use the code “as is” but have to delete these lines.

First I just get the Login Guid. You’ll now ask: “How the hell did he get the login guid…? This file is supposed to be on the “other” server where no session variables are available…!” Right, I tested the RqlBridge on just ONE server (my editorial server), but the functionality also works when there are two servers.

sLoginGUID = Session("LoginGUID")

'Then the RQL statement is written in the variable "xmlString".
xmlString = "<IODATA loginguid=""" & sLoginGUID & """>"&_
"<PROJECTS action=""list""/>"&_

'Here we call the file "RqlBridge.asp" (on our editorial server)
'and transfer the RQL statement (xmlString) as the content of
'the parameter sXmlData.  
'As written above the RqlBridge is just being used to execute the RQL. 
'So as a result of this call we receive the server response from the editorial server.
RqlRequest = GetServerAnswer("http://localhost/cms/plugins/remoterql/rqlbridge.asp?sXmlData=" & xmlString)
Response.Write "<br>Server Response:" & server.htmlencode(RqlRequest) & "<p>"

'The function GetServerAnswer just calls an URL and returns the response.
'This is not related to the Management Server but is more a general functionality.
Function GetServerAnswer(sUrl)
  Dim objHTTP, sServerAnswer
  Set objHTTP = Server.CreateObject("WinHttp.WinHttpRequest.5.1")
  objHTTP.SetTimeouts 0, 3000, 2000, 5000
  objHTTP.open "GET", sUrl, false
  if err.Number <> 0 then
  end if
  on error goto 0 
  GetServerAnswer = sServerAnswer
end function

Ready! We are now able to create calls on server A that will be executed on server B. I don’t know if this is helpful for much people but at least I wanted to point out this option.


Working with dates

As soon as you would like to read out the creation date of a page or the appearance schedule for a page you’ll notice that the dates are not really readable as they are just floating point number.  So if  you would like to display a date in a way that people can read it, you have to encode the date. If you would like to save a date….you have to decode it previously ;) The code below demonstrates both directions. If you create a plugin based on this code you will see how a serial date will be converted into a floating point number and vice versa.

  'converts a serial date into a floating point number that can be stored into the database
  mydate = "11/11/2010"
  set RQLObject = Server.CreateObject("RDCMSAsp.RdPageData")
  mydate = RqlObject.EncodeDate(myDate)
  response.write mydate & "<br>"
  mydate = "30493"
  set RQLObject = Server.CreateObject("RDCMSAsp.RdPageData")
  mydate = RqlObject.DecodeDate(myDate)
  response.write mydate & "<br>"'converts a date (floating point number) into a serial date ....that can be understood by humans ;-)


sendXML function

In order to enhance the overview of  the code in your applications you might want to have an area where you just place the RQL functions and another area where you implement the logic. But even the execution of the RQL statements can be excluded in a seperate function. Of course this is not that much but at least we save a few lines of code.

function sendXML (XMLString)
  set objData = server.CreateObject("RDCMSASP.RdPageData")    
  objData.XmlServerClassName = "RDCMSServer.XmlServer"
  sendXML = objData.ServerExecuteXml(XMLString, sErrors)
  if sErrors <> "" then     
    response.write "Errors occured: " & sErrors & chr(13) & XMLString & "<br>"
  end if
  objData = NULL
end function

If you found this article helpful and would like to see, what other users have done with RQL, then please visit the Community web site under www.SolutionsExchange.info
If you find any errors or have questions, please just leave a comment and I’ll try to help. If you’re interested in more RQL related articles then….right…leave a comment.

Have fun with RQL!

Source: RQL in a nutshell - Part II

© copyright 2011 by Manuel Schnitger