Alternative XML API
Last modified by Vincent Massol on 2021/03/18 11:28
Proof of concept for XML based api |
Type | Snippet |
Category | |
Developed by | xwiki:XWiki.yish |
Rating | |
License | GNU 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[&targetClass=[classname]][&targetObject=[objectName]][&fields=[field1,flield2,..]][&list=true]][&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
## 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[&targetClass=[classname]][&targetObject=[objectName]][&fields=[field1,flield2,..]][&list=true]][&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