Skip to content

Instantly share code, notes, and snippets.

@larscwallin
Created June 7, 2012 09:23
Show Gist options
  • Save larscwallin/2887831 to your computer and use it in GitHub Desktop.
Save larscwallin/2887831 to your computer and use it in GitHub Desktop.
XPDO to JSON-SCHEMA XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" />
<xsl:output method="text" />
<xsl:output indent="yes" />
<xsl:output media-type="text/plain" />
<xsl:param name="directory"/>
<xsl:param name="label-composite">Composites</xsl:param>
<xsl:param name="label-aggregate">Aggregates</xsl:param>
<xsl:param name="xpdo-model"></xsl:param>
<xsl:param name="include-objects">*</xsl:param>
<xsl:param name="include-dependencies">1</xsl:param>
<xsl:param name="include-local-only">0</xsl:param>
<xsl:param name="schema-base-url">#</xsl:param>
<xsl:param name="ident">
<xsl:text> </xsl:text>
</xsl:param>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="model">
{
"model":"<xsl:value-of select="./@package" />",
"version":"<xsl:value-of select="./@version" />",
"schema":[
<xsl:for-each select="./object">
<xsl:if test="contains($include-objects,@class) or $include-objects='*'">
<xsl:call-template name="xpdo-object" >
<xsl:with-param name="skip-delimiter">0</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
]}
</xsl:template>
<xsl:template name="xpdo-object" match="object">
<xsl:param name="object" />
<xsl:param name="skip-delimiter" />
<xsl:param name="schema-base-url" />
<xsl:for-each select="."> {
"type":"object",
"description": "<xsl:value-of select="@class" />",
"extends":"<xsl:value-of select="@extends" />",
"properties": {
"id":{
"description": "id",
"type": "integer"
}
<xsl:for-each select="//object[@class=current()/@class]/field">
<xsl:apply-templates select="current()" />
</xsl:for-each>
<xsl:choose>
<xsl:when test="$include-dependencies=1">
<xsl:choose>
<xsl:when test="$include-local-only=1 and count(./aggregate) > 0">
<xsl:apply-templates select="./aggregate[@owner!='foreign']" />
</xsl:when>
<xsl:otherwise>
<xsl:if test="count(./aggregate) > 0">
<xsl:call-template name="aggregate-inline" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="count(./composite) > 0">
<xsl:call-template name="composite-inline" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
},
"links": [
<xsl:choose>
<xsl:when test="$include-dependencies=1">
<xsl:choose>
<xsl:when test="$include-local-only=1">
<xsl:apply-templates select="./aggregate[@owner!='foreign']">
<xsl:with-param name="schema-base-url" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="./aggregate">
<xsl:with-param name="schema-base-url" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="./composite">
<xsl:with-param name="schema-base-url" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
]
}
</xsl:for-each>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:template>
<xsl:template match="field[@phptype='string']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "string",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='json']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "object",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='integer']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "integer",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='date']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "string",
"format": "date",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='boolean']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"name": "<xsl:value-of select="@key" />",
"type": "boolean",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"defaultValue":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='datetime']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "string",
"format": "datetime",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="field[@phptype='timestamp']">
<xsl:text> ,"</xsl:text><xsl:value-of select="@key" /><xsl:text>":{</xsl:text>
"type": "string",
"format": "timestamp",
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="@null" /></xsl:call-template>,
"default":"<xsl:value-of select="@default" />"
}
</xsl:template>
<xsl:template match="aggregate">
<xsl:param name="schema-base-url" />
{
"rel": "<xsl:value-of select="./@class" />",
"href": "#",
"targetSchema": "<xsl:value-of select="$schema-base-url" />/<xsl:value-of select="./@class" />"
}
</xsl:template>
<xsl:template match="composite">
<xsl:param name="schema-base-url" />
,{
"rel": "<xsl:value-of select="./@class" />",
"href": "#",
"targetSchema": "<xsl:value-of select="$schema-base-url" />/<xsl:value-of select="./@class" />"
}
</xsl:template>
<xsl:template name="aggregate-inline">
<xsl:text> ,"</xsl:text><xsl:value-of select="./aggregate/@class" /><xsl:text>":{</xsl:text>
<xsl:choose>
<xsl:when test="./aggregate/@owner='local' and ./aggregate/@cardinality='many'">
"type": "array",
"items":{
"type":"string"
},
</xsl:when>
<xsl:otherwise>
"type": "string",
</xsl:otherwise>
</xsl:choose>
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="./aggregate/@null" /></xsl:call-template>,
"rel": "<xsl:value-of select="./aggregate/@class" />"
}
</xsl:template>
<xsl:template name="composite-inline">
<xsl:text> ,"</xsl:text><xsl:value-of select="./composite/@class" /><xsl:text>":{</xsl:text>
<xsl:choose>
<xsl:when test="./composite/@owner='local' and ./composite/@cardinality='many'">
"type": "array",
"items":{
"type":"string"
},
</xsl:when>
<xsl:otherwise>
"type": "string",
</xsl:otherwise>
</xsl:choose>
"required":<xsl:call-template name="resolveBoolean"><xsl:with-param name="bool" select="./composite/@null" /></xsl:call-template>,
"rel": "<xsl:value-of select="./composite/@class" />"
}
</xsl:template>
<xsl:template name="resolveBoolean">
<xsl:param name="bool" />
<xsl:choose>
<xsl:when test="$bool = 'false'">
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>false</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<!--
<validation>
<rule field="category" name="preventBlank" type="xPDOValidationRule" rule="xPDOMinLengthValidationRule" value="1" message="category_err_ns_name" />
</validation>
<validation>
<rule field="name" name="invalid" type="preg_match" rule="/^(?!\s)[a-zA-Z0-9\x2d-\x2f\x7f-\xff_-\s]+(?!\s)$/" message="tv_err_invalid_name" />
<rule field="name" name="reserved" type="preg_match" rule="/(?!^(id|type|contentType|pagetitle|longtitle|description|alias|link_attributes|published|pub_date|unpub_date|parent|isfolder|introtext|content|richtext|template|menuindex|searchable|cacheable|createdby|createdon|editedby|editedon|deleted|deletedby|deletedon|publishedon|publishedby|menutitle|donthit|haskeywords|hasmetatags|privateweb|privatemgr|content_dispo|hidemenu|class_key|context_key|content_type)$)/" message="tv_err_reserved_name" />
</validation>
<validation>
<rule field="name" name="name" type="xPDOValidationRule" rule="xPDOMinLengthValidationRule" value="1" message="content_type_err_ns_name" />
</validation>
<validation>
<rule field="name" name="invalid" type="preg_match" rule="/^(?!\s)[a-zA-Z0-9\x2d-\x2f\x7f-\xff_-\s]+(?!\s)$/" message="chunk_err_invalid_name" />
</validation
<validation>
<rule field="category" name="preventBlank" type="xPDOValidationRule" rule="xPDOMinLengthValidationRule" value="1" message="category_err_ns_name" />
</validation>
-->
{
"jsonschema":[
{
"type":"object",
"description":"modChunk",
"extends":"modElement",
"properties":{
"id":{
"description":"id",
"type":"integer"
},
"name":{
"type":"string",
"required":true,
"default":""
},
"description":{
"type":"string",
"required":true,
"default":"Chunk"
},
"editor_type":{
"type":"integer",
"required":true,
"default":"0"
},
"category":{
"type":"integer",
"required":true,
"default":"0"
},
"cache_type":{
"type":"integer",
"required":true,
"default":"0"
},
"snippet":{
"type":"string",
"required":false,
"default":""
},
"locked":{
"name":"locked",
"type":"boolean",
"required":true,
"defaultValue":"0"
},
"static":{
"name":"static",
"type":"boolean",
"required":true,
"defaultValue":"0"
},
"static_file":{
"type":"string",
"required":true,
"default":""
},
"modCategory":{
"type":"string",
"required":false,
"rel":"modCategory"
},
"modElementPropertySet":{
"type":"array",
"items":{
"type":"string"
},
"required":false,
"rel":"modElementPropertySet"
}
},
"links":[
{
"rel":"modCategory",
"href":"#",
"targetSchema":"/modCategory"
},
{
"rel":"modElementPropertySet",
"href":"#",
"targetSchema":"/modElementPropertySet"
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment