Google Groups Home
Help | Sign in
Recent pages and files
apml-json    
Request for comments on this proposal for APML-JSON. Cheers.


By David Novakovic and Ben Novakovic

 

APML JSON

Rationale

As more and more web applications become APML aware there will be services delivering "APML-Like" data as JSON, often converted directly from APML itself. This document seeks to outline a sane specification for JSON-APML to take the guess work out of it for developers seeking to do work with APML in Javascript, or even seeking a lightweight alternative to APML itself. Henceforth in this document the original APML spec will be referred to as "APML" and the new JSON specification will be referred to as "APML-JSON".

 

For the most part this specification will mirror the original APML specification as closely as possible. The largest difference is that where a NodeList of Concept/Source nodes with "key" attributes exist in the APML spec now are replaced with keyword indexed values in a JSON associative array. This will become clearer in the example. 

Another relatively large difference is the use of camelCase for keys that are capitalised in the XML nodes, rather than all caps. This is a compromise between the reccomendation of W3 for using no caps with underscores and the APML all caps way. Naturally people will do what they want. ;)  Additionally, with  the JSON version, if fields are missing, they are just assumed to be empty, this saves having to transmit redundant markup.

 

Examples

To see an example of javascript using JSON with this notation, head

over to Ben Novakovic\\47s example at http://bmn.name/examples/apml/ .

Look at the source to see the javascript.

 

APML-JSON Breakdown

Basically the root element contains two main parts, the head and the body:

 

{

    "head":{},

    "body":{}

}
 

The head contains some metadata:

 

"head": {

    "version": 0.6,

    "title": "Example APML-JSON file for apml.org",

    "generator": "Written by Hand",

    "userEmail": "sam...@apml.org",

    "dateCreated": "2007-03-11T01:55:00Z"

}
 

Then the body contains some profiles and also has a default profile:

 

"body": {

    "defaultProfile": "Work",

    "profiles": {}

}
 

Each profile contains explicitdata and implicitdata

 

"profiles": {

    "work": {

        "implicitData": {},

        "explicitData": {}

    }

    "home": {

        "implicitData": {},

        "explicitData": {}

    }

}
 

Explicit data and implicit data are similar with slightly different attribute, so we\\47ll look aty implicit ones here. There will be examples of others in the example APML-JSON file that will be at the end of this documents. Data can be in the form of sources or concepts.

 

"implicitData": {

    "concepts": {

        "attention": {

            "value": "1.0",

            "from": "",

            "updated": "2007-03-11T01:55:00Z"

        },

        "content distribution": {

            "value": "1.0",

            "from": "GatheringTool.com",

            "updated": "2007-03-11T01:55:00Z"

        }

    },

    "sources":   {

        "http://feeds.feedburner.com/apmlspec": {

            "name": "APML.org",

            "value": "1.0",

            "type":  "application/rss+xml",

            "value": "0.4"

        }

    }

}
 

Sources can also contain an Author.

 

"http://feeds.feedburner.com/apmlspec": {

    "name": "APML.org",

    "value": "1.00",

    "type":  "application/rss+xml",

    "value": "0.4"

    "author": {

            "key": "Sample",

            "value": "0.5",

            "from": "GatheringTool.com",

            "updated": "2007-03-11T01:55:00Z"

    }

}
 

So here we have a full example:

 

{

    "head": {

           "version": "0.6",

           "title": "Example APML-JSON file for apml.org",

           "generator": "Written by Hand",

           "userEmail": "sample@apml.org",

           "dateCreated": "2007-03-11T01:55:00Z"

    },

    "body": {

        "defaultProfile": "Work",

        "profiles": {

            "work": {

                "implicitData": {

                    "concepts": {

                        "attention": {

                            "value": 0.1,

                            "from": "Sometool.com",

                            "updated": "2007-03-11T01:55:00Z"

                        },

                        "content distribution": {

                            "value": 0.1,

                            "from": "Sometool.com",

                            "updated": "2007-03-11T01:55:00Z"

                        }

                    },

                    "sources":   {

                        "http://feeds.feedburner.com/apmlspec": {

                            "name": "APML.org",

                            "value": 1.00,

                            "type":  "application/rss+xml"

                            "authors": {

                                "Sample":{

                                    "value": 0.5,

                                    "from": "GatheringTool.com",

                                    "updated": "2007-03-11T01:55:00Z"

                                }

                            }

                        }

                    }

                },

                "explicitData": {

                    "concepts": {

                        "attention": {

                            "value": 0.1

                        },

                        "content distribution": {

                          "value": 0.1,

                        }

                    },

                    "sources":   {

                        "http://feeds.feedburner.com/apmlspec": {

                            "name": "APML.org",

                            "value": "1.00",

                            "type":  "application/rss+xml"

                            "authors": {

                                "Sample": {

                                    "value": 0.5,

                                }

                            }

                        }

                    }

                }

            },

            "home": {

                "implicitData": {},

                "explicitData": {}

            }

        },

        "applications": {

            "sample.com": {

                "sampleAppEI": {}

            }

        }

    }

 

XSLT for APML to APML-JSON

apml2json.xslt

 


\\46lt;xsl:stylesheet version = \\46#39;1.0\\46#39;
xmlns:xsl=\\47http://www.w3.org/1999/XSL/Transform\\47
xmlns:a="http://www.apml.org/apml-0.6"\\46gt;
\\46lt;xsl:output
method = "text"
omit-xml-declaration = "yes"
standalone = "yes"
/\\46gt;
\\46lt;!--

A stylesheet to convert APML-XML data to APML-JSON data.
For info on APML, visit http://apml.org

These templates are very straightfoward and indented to help people read them.
As a consequence of readability, there is lots of whitespace in the results,
normalise and refactor brutally if you use this in production.
Additionally these simple templates will be easily modified to suit the
upcoming APML v1.0 specification.

If you wish to deal with application specific data add a template like:

\\46lt;xsl:template match="a:Application"\\46gt;
handle application data
\\46lt;/xsl:template\\46gt;

Please email davidnovakovic _ at _ gmail.com with bugs/patches/fixes.
This code is contributed "as is" courtesy of comvine Pty Ltd.

--\\46gt;
\\46lt;xsl:template match="/"\\46gt;
{
\\47head\\47:{
\\46#39;version\\46#39;: \\46#39;\\46lt;xsl:value-of select="/a:APML/@version"/\\46gt;\\46#39;,
\\46lt;xsl:for-each select="/a:APML/a:Head/*"\\46gt;
\\46#39;\\46lt;xsl:value-of select="name()" /\\46gt;\\46#39;:\\46#39;\\46lt;xsl:value-of select="."/\\46gt;\\46#39;,
\\46lt;/xsl:for-each\\46gt;
},
\\47body\\47:{
\\46#39;defaultProfile\\46#39;: \\46#39;\\46lt;xsl:value-of select="/a:APML/a:Body/@defaultprofile"/\\46gt;\\46#39;,
\\46lt;xsl:if test="count(/a:APML/a:Body/a:Profile) \46gt; 0"\\46gt;
\\47profiles\\47:{
\\46lt;xsl:for-each select="/a:APML/a:Body"\\46gt;
\\46lt;xsl:apply-templates select="a:Profile"/\\46gt;
\\46lt;/xsl:for-each\\46gt;
},
\\46lt;/xsl:if\\46gt;
\\46lt;xsl:if test="count(/a:APML/a:Body/a:Applications) \46gt; 0"\\46gt;
\\47applications\\47:{
\\46lt;xsl:for-each select="/a:APML/a:Body/a:Applications"\\46gt;
\\46lt;xsl:apply-templates select="a:Application"/\\46gt;
\\46lt;/xsl:for-each\\46gt;
}
\\46lt;/xsl:if\\46gt;
}
}
\\46lt;/xsl:template\\46gt;

\\46lt;!-- This template matches Profile Nodes, this is where we handle
implicit and explicit data --\\46gt;
\\46lt;xsl:template match="a:Profile"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@name"/\\46gt;\\46#39;:{
\\47implicitData\\47:{
\\46lt;xsl:for-each select="a:ImplicitData/*"\\46gt;
\\46lt;xsl:if test="name() = \\46#39;Concepts\\46#39;"\\46gt;
"concepts":{
\\46lt;xsl:for-each select="a:Concept"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key" /\\46gt;\\46#39;:{
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value" /\\46gt;,
\\46#39;from\\46#39;:\\46#39;\\46lt;xsl:value-of select="@from" /\\46gt;\\46#39;,
\\46#39;updated\\46#39;:\\46#39;\\46lt;xsl:value-of select="@updated" /\\46gt;\\46#39;
},
\\46lt;/xsl:for-each\\46gt;
},
\\46lt;/xsl:if\\46gt;
\\46lt;xsl:if test="name() = \\46#39;Sources\\46#39;"\\46gt;
"sources":{
\\46lt;xsl:for-each select="a:Source"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key" /\\46gt;\\46#39;:{
\\46#39;name\\46#39;:\\46#39;\\46lt;xsl:value-of select="@name" /\\46gt;\\46#39;,
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value" /\\46gt;,
\\46#39;type\\46#39;:\\46#39;\\46lt;xsl:value-of select="@type" /\\46gt;\\46#39;,
\\46#39;from\\46#39;:\\46#39;\\46lt;xsl:value-of select="@from" /\\46gt;\\46#39;,
\\46#39;updated\\46#39;:\\46#39;\\46lt;xsl:value-of select="@updated" /\\46gt;\\46#39;,
\\46lt;xsl:if test="count(a:Author) \46gt; 0"\\46gt;
\\47authors\\47: {
\\46lt;xsl:for-each select="a:Author"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key"/\\46gt;\\46#39;:{
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value"/\\46gt;,
\\46#39;from\\46#39;:\\46#39;\\46lt;xsl:value-of select="@from"/\\46gt;\\46#39;,
\\46#39;updated\\46#39;:\\46#39;\\46lt;xsl:value-of select="@updated"/\\46gt;\\46#39;
},
\\46lt;/xsl:for-each\\46gt;
}
\\46lt;/xsl:if\\46gt;
},
\\46lt;/xsl:for-each\\46gt;
}
\\46lt;/xsl:if\\46gt;
\\46lt;/xsl:for-each\\46gt;
},
\\47explicitData\\47:{
\\46lt;xsl:for-each select="a:ExplicitData/*"\\46gt;
\\46lt;xsl:if test="name() = \\46#39;Concepts\\46#39;"\\46gt;
"concepts":{
\\46lt;xsl:for-each select="a:Concept"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key" /\\46gt;\\46#39;:{
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value" /\\46gt;,
},
\\46lt;/xsl:for-each\\46gt;
},
\\46lt;/xsl:if\\46gt;
\\46lt;xsl:if test="name() = \\46#39;Sources\\46#39;"\\46gt;
"sources":{
\\46lt;xsl:for-each select="a:Source"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key" /\\46gt;\\46#39;:{
\\46#39;name\\46#39;:\\46#39;\\46lt;xsl:value-of select="@name" /\\46gt;\\46#39;,
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value" /\\46gt;,
\\46#39;type\\46#39;:\\46#39;\\46lt;xsl:value-of select="@type" /\\46gt;\\46#39;,
\\46lt;xsl:if test="count(a:Author) \46gt; 0"\\46gt;
\\47authors\\47: {
\\46lt;xsl:for-each select="a:Author"\\46gt;
\\46#39;\\46lt;xsl:value-of select="@key"/\\46gt;\\46#39;:{
\\46#39;value\\46#39;:\\46lt;xsl:value-of select="@value"/\\46gt;,
},
\\46lt;/xsl:for-each\\46gt;
}
\\46lt;/xsl:if\\46gt;
},
\\46lt;/xsl:for-each\\46gt;
}
\\46lt;/xsl:if\\46gt;
\\46lt;/xsl:for-each\\46gt;
}
},
\\46lt;/xsl:template\\46gt;

\\46lt;xsl:template match="rmv_white"\\46gt;
\\46lt;/xsl:template\\46gt;

\\46lt;/xsl:stylesheet\\46gt;
Version: 
Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google