R/namespaceHandlers.R

namespaceNodeHandlers =
  #
  # This is to manage a collection of node handlers 
  # which have handlers for nodes with the same name but in an
  # different namespace.
  # For example, suppose we have a node array  in an R representation
  # and another in Matlab but these are differentiated by the namespace.
  # r:array and m:array.
  # This function arranges to invoke the correct handler when a node is encountered.
  #
  #  namespaceNodeHandlers("r:array" = function(...) ...,
  #                        "m:array" = function(...) ...,
  #                        other = function(...) ...)
  #
  #
  #  namespaceNodeHandlers("r:array" = function(...) ...,
  #                        "m:array" = function(...) ...,
  #                        other = function(...) ...,
  #                        nsDefs= c(r = "http://www.r-project.org",
  #                                  m = "http://www.mathworks.com")  )
  #
  #
  # If there is no handler for a given node, then call the default one
  # i.e. .startElement or startElement
  #
function(..., .handlers = list(...), nsDefs = NULL, useDotNames = TRUE)
{
   # Get the node name and namespace prefix/alias for each of the handler names
  tmp = strsplit(names(.handlers), ":")

  prefix = sapply(tmp, function(x) if(length(x) > 1) x[1] else "")
  nodeNames = sapply(tmp, function(x) if(length(x) > 1) x[2] else x[1])

   # Now, find out which ones are duplicated.
  w = duplicated(nodeNames)
  if(!any(w))
    return(.handlers)

  dups = nodeNames[w]
  
    # Now, take out the handler functions that have the same node name
    # as any other.
  w = nodeNames %in% dups 
  nsHandlers = .handlers[ w ]
    # and remove them from .handlers
  .handlers = .handlers[ !w ]


    # This function will act as the proxy for doing the dispatch for a particular node.
  generalHandler =
  function(node, ...) {

       # Get the node name and the namespace prefix.
      id = xmlName(node)

      ns = xmlNamespace(node)

      if(is.null(ns))
        ns = ''
      
      if(length(nsDefs)) {
          # get the namespace definition from the node
          # and its URI and then match this to the nsDefs
          # That gives us the prefix to use

        i = (ns == nsDefs)
        if(!any(i) && ns != '')
          ns = character() #stop("can't match namespace '", as.character(ns), "' in ", paste(nsDefs, collapse = ", "))
        else
          ns = names(nsDefs)[i]
      }

      if(length(ns) && ns != "")
        tmp = paste(ns, id, sep = ":")
      else
        tmp = id

      f = nsHandlers[[ tmp ]]

        # if we didn't find a handler, use the startElement one
      if(is.null(f)) 
        f = .handlers[[ if(useDotNames) '.startElement' else 'startElement' ]]

        # if we have a handler, call it.
        # Otherwise, just return the node... after all that!
      if(!is.null(f))       
        f(node, ...)
      else
        node
    }


   .handlers[ dups ] = rep(list(generalHandler), length(dups))

   class(.handlers) <- "XMLNamespaceNodeHandlers"

   if(length(nsDefs))
     class(.handlers) <- c(class(.handlers), "RequiresNamespaceInfo")

   .handlers
}  

Try the XML package in your browser

Any scripts or data that you put into this service are public.

XML documentation built on Nov. 3, 2023, 1:14 a.m.