Alternative XML API

Last modified by Vincent Massol on 2021/03/18 11:28

cogProof of concept for XML based api
TypeSnippet
Category
Developed by

xwiki:XWiki.yish

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

Table of contents

Description

It is meant to be used programmatically by web service providers who wish to syndicate, encapsulate or offer an alternative interface.

This API hides classes under XWiki. for security reasons

 The page expects calls of the form:

genericXML?xpage=rdf[&targetClass=[classname]][&targetObject=[objectName]][&fields=[field1,flield2,..]][&list=true]][&getScheme=true]]

Where:

  • xpage=rdf: if set, produce xml. if missing, produce a form and brief help text.
  • targetClass: if specified, query only this class
  • targetObject: if specified, query only this object
  • fields: comma separated list of fields to display. if empty, display all.
  • list: list only, display object names only.
  • getScheme: display scheme, i.e. list classes and property names

A potential client could call

genericXML?xpage=rdf&getScheme=true

To list all classes,

Then call 

genericXML?xpage=rdf&targetClass=SomeClass&list=true

To list objects of a particular class Then call

genericXML?xpage=rdf&targetClass=SomeClass&targetObject=SomeObject&fields=field1,flield2

To retrieve field1 and field2 of object SomeObject from class SomeClass

Human clients who reach the page are displayed with a brief human-readable explanation, and a form to activate the API.

Of course, this is just an example. You may prefer a different scheme, for example - having a single structure for all objects.

#######
## print class structure, as:
## <class id="ClassName">
##   <property>Property1Name</property>
##   <property>Property2Name</property>
## </class>
#######
#macro(printClass $class)
## Hide system classes
#if(!$class.startsWith("XAppClasses") && !$class.startsWith("XWiki"))
<class id="$class">
  #set ($properties = $xwiki.getClass($class).getProperties())
  #foreach($property in $properties)
 <property>$property.getName()</property>
  #end
</class>
#end ## Hide system classes
#end ##printclass
#######
## if the request has "?xpage=rdf", produce XML otherwise, produce html.
## this is a hack, relying on the fact that XWiki skips the skin for  "?xpage=rdf"
#######
#if($request.xpage == "rdf")
$response.setContentType("text/xml")
<xml>
#if($request.targetClass && ($request.targetClass.length() > 2))
  #set ($className = $request.targetClass)
#end
## Hide system classes
#if(!$class.startsWith("XAppClasses") && !$class.startsWith("XWiki"))
#if($request.getScheme) ## get scheme
  #if($className)
     #printClass($className)
  #else
     #set ($classes = $xwiki.getClassList())
     #foreach ($class in $classes)
        #printClass($class)
     #end
  #end
#else  ## get data
#if(!$className)
  #set ($className = 'Blog.BlogCategories')                   ## random default, just to make life easier.
#end
#if($request.fields && $request.fields.length() > 0)
#set($fields = $request.fields.split(","))                    ## parse field1,field2,...
#end
#if($request.targetObject && $request.targetObject.length() > 0)
#set($objName = $request.targetObject)
#end
#if($request.list)
  #set($listOnly = true)
#end
### get scheme?
#set ($hql = ", BaseObject as obj where obj.name=doc.fullName and obj.className='${className}' and obj.name<>'${className}Template'")
#if($objName)
#set ($hql = $hql+" and obj.name='$objName'")                 ## if object name specified, add it to the query.
#end                                                          ## a bit lazy here.
#set ($items= $xwiki.searchDocuments($hql))
#if ($items.size() > 0)
#foreach ($item in $items)
   #set ($itemDoc = $xwiki.getDocument($item)
   #set ($itemObj = $itemDoc.getObject("$className"))
  <$className name="$item" url="itemDoc.getURL()">         ## print object opening tag
   #set($class = $itemObj.xWikiClass)
      #if($fields)                                          ## specific fields requested, so ignore "list" mode
         #foreach($field in $fields)
            #set($fieldVal  = $itemObj.get($field))
           <$field>$fieldVal</$field>                      ## print property
         #end
      #else
         #if(!$listOnly)                                    ## if list mode - skip properties
           #foreach($prop in $class.properties)
             #set($propName = $prop.getName())
             #set($propValue  = $itemObj.get($propName))    ## print property
            <$propName>$xwiki.getXMLEncoded(${propValue})</$propName>
          #end
        #end
      #end
  </$className>                                            ## close object
#end
#end
#end ## if: get scheme
#end ## if: Hide system classes
</xml>
#else                                        ## not $request.xpage == "rdf", print form for humans
<form action="">
<input type="hidden" name="xpage" value="rdf" />
Class:
<input type="text" name="targetClass" size="10" />
Object:
<input type="text" name="targetObject" size="10" />
Fields:
<input type="text" name="fields" size="20" /><br/>
List objects<input type="checkbox" name="list" value="true" />
Show scheme<input type="checkbox" name="getScheme" value="true" />
<input type="submit" />
</form>

1.1.1 The expected syntax for an API call is:
*\{code\}http://patternlanguagenetwork.myxwiki.org/xwiki/bin/view/api/genericXML?xpage=rdf[&amp;targetClass=[classname]][&amp;targetObject=[objectName]][&amp;fields=[field1,flield2,..]][&amp;list=true]][&amp;getScheme=true]]\{code\}*
* *xpage=rdf*: if set, produce xml. if missing, produce this form.
* *targetClass*: class to export, default is Patterns.PatternsClass
* *targetObject*: if specified, query only this object
* *fields*: comma separated list of fields to display. if empty, display all.
* *list*: list only, display object names only.
* *getScheme*: display scheme, i.e. list classes and property names

#end
Tags: xml API
     

Get Connected