NaviServer Programmable Web Server

ns_adp_register(n)

NaviServer Built-in Commands – 5.0.4


[ Main Table Of Contents | Table Of Contents | Keyword Index ]

Name

ns_adp_register - Creating Custom ADP Tags

Table Of Contents

Synopsis

Description

These commands enable the definition of custom ADP tags (application-specific, XML-like tags) which are expanded whenever ADP content (.adp files or ADP strings processed via ns_adp_parse) is processed. Registering application-specific ADP tags is a means to include script-driven, application-specific content in a web page, providing an alternative to embedding scripts in ADP pages via the <% script %> syntax as described in the ADP Overview man page.

Registered tags can either be tags with content -- consisting of an opening and a closing tag -- or tags defining empty elements, where no closing tag is defined. When both the tag and the endtag are specified in the registering command, the tags must have content; when the endtag is omitted in the registering command, empty elements are defined.

COMMANDS

ns_adp_registeradp tag ?endtag? adpstring

Registers an ADP snippet adpstring to be included when the specified tag is encountered while parsing the ADP content. The tag argument specifies the tag that will trigger the inclusion of the parsed ADP fragment adpstring.

If the optional endtag argument is specified, the content between the opening and closing tags is replaced by the adpstring, and the enclosed content is discarded. This behavior differs from the other tag registering commands, where the enclosed content can be processed or passed to the handler.

Note: Attributes specified in the tag are not accessible when using ns_adp_registeradp. If you need to access attributes or the enclosed content, consider using ns_adp_registerproc or ns_adp_registerscript.

 # Register an ADP snippet to display the current date as tag "printdate"
 ns_adp_registeradp printdate {
      The current date is: <% ns_adp_puts [ns_httptime [ns_time]] %>
 }

Usage example in an ADP page:

 ... header ...
 <p>This is my page.</p>
  <printdate>
 ... footer ...
ns_adp_registerproc tag ?endtag? proc

Registers a Tcl procedure to be evaluated when the given tag is encountered in ADP content.

This command is intended for positional and lightweight tag handlers. Only the value* of the attributes specified in the tag are passed to the procedure proc; attribute names are discarded. Attribute values are passed as positional arguments, in the order in which they appear in the tag.

If the optional endtag is specified, the procedure will receive one additional final argument containing the literal content enclosed between the opening and closing tags. The enclosed content is not evaluated and is passed unchanged as a single text block.

The procedure proc will be called with a variable number of arguments, one for each attribute value provided in the tag. If the endtag argument is specified, the procedure will also receive a final argument containing the content enclosed between the tags. No evaluation of the enclosed content is performed; it is passed as a single text block.

When the procedure is invoked, its return value replaces the tag (and the enclosed content, if endtag is specified) in the output.

 # Define the tag handler
 proc geturltag {args} {
    # Extract the URL from the last argument
    set url [lindex $args end]
    # Extract any options (attributes)
    set options [lrange $args 0 end-1]
    # Perform an HTTP GET request
    set response [ns_http run {*}$options $url]
    # Return the response body
    dict get $response body
 }
 
 # Register the tag handler with an opening and closing tag
 ns_adp_registerproc geturl /geturl geturltag

Usage example in an ADP page:

 ... header ...
 <p>This is my page.
 
 <geturl -timeout 3s >https://example.com/hello.html</geturl>
 
 <p>Next paragraph.</p>
 ... footer ...

Note:

  • Only attribute values are passed to the procedure; attribute names are not available.

  • Attribute values are passed positionally, in the order they appear in the tag.

  • This command is suitable when attribute names are irrelevant and a simple positional calling convention is sufficient.

 proc ::reporttags {args} {
   return $args
 }
 ns_adp_registerproc reporttags  ::reporttags
 
 ns_adp_parse -string {<reporttags CamelCase x=X A=a>}
 # Returns: CamelCase X a
ns_adp_registerscript tag ?endtag? proc

Registers a Tcl procedure proc to be evaluated when the given tag is encountered in ADP content.

This command provides structured access to tag attributes and is intended for cases where attribute names and values must be distinguished. Attributes are passed to the procedure as an ns_set containing name/value pairs.

If the tag is registered with an endtag, the procedure is invoked with two arguments: first, the enclosed content as a string, and second, the ns_set containing the tag attributes. When registered without an end tag, the procedure is called with a single argument (the ns_set of attributes).

Attributes specified without an explicit value (no equals sign) are stored in the ns_set with their name as the value.

When the tag is parsed, it is replaced by the result of the registered proc.

 # Define the tag handler
 proc onday {string attributes} {
   # Get the 'day' attribute
   set day [ns_set get -nocase $attributes day]
   
   # Check if the current date matches the specified day
   if {[ns_fmttime [ns_time] "%m/%d"] eq $day} {
     return $string
   }
 }
 
 # Register the tag handler with an opening and closing tag #
 ns_adp_registerscript onday /onday onday

Usage example in an ADP page:

 ... header ...
 <p>This is my page.</p>
 
 <onday day="12/25"><p>Merry Christmas and a Happy New Year</p></onday>
 
 <p>Next paragraph.</p>
 ... footer ...

Note:

  • Attribute names and values are available via the ns_set passed to the procedure.

  • Attribute order is not significant.

  • This command should be used when tag behavior depends on specific attribute names or optional flags.

The following is a simple way of handling conditional content in ADPs:

 # Store content in a global variable
 proc remember {input tagset} {
   set tagname [ns_set get -nocase $tagset name]
   if {$tagname eq ""} {
     set ::_adp_memory($tagname) $input
     return ""
   } else {
     return $input
   }
 }
 
 # Retrieve and parse stored content
 proc recall {name} {
   if {[info exists ::_adp_memory($name)]} {
     set parsecommand [list ns_adp_parse -string]
     lappend parsecommand $::_adp_memory($name)
     ns_adp_puts -nonewline [uplevel $parsecommand]
   } else {
     ns_log Error "[ns_adp_argv 0]: Unable to recall"
   }
 }

If the preceding Tcl has been executed (perhaps during server startup), then the following ADP fragment displays the results of a database query in a table, or shows "No rows in result." if there are no rows:

 <%
  set rows {}
  set db [ns_db gethandle]
  ns_db exec "select somecolumn from sometable"
  set row [ns_db bindargs $db]
  while {[ns_db getrow $db $row]}  {
      lappend rows [ns_set get $row "somecolumn"]
  }
  ns_db releasehandle $db
 %>
 
 <remember name="has-rows_header"> <table> </remember>
 <remember name="hasrows_rows"> <tr><td><%=$column%></td></tr> </remember>
 <remember name="hasrows_footer"> </table> </remember>
 No rows in result.
 <remember name="norows">
 
 <%
  if {[llength $rows] > 0}  {
    recall "hasrows_header"
    foreach row $rows {
      set column $row
      recall "hasrows_rows"
    }
    recall "hasrows_footer"
  } else {
    recall "norows"
  }
 %>

In this example, the `remember` procedure stores different parts of the output, and the `recall` procedure retrieves and processes them conditionally based on whether there are rows from the database query.

See Also

ns_adp, ns_adp_include, ns_register, ns_set

Keywords

ADP, custom tags, server built-in, tag