CurieJavascript

From XHTML2
Jump to: navigation, search

Below is a simple example Javascript object that allows for the ready extraction and manipulation of attribute values that are CURIEs.

// An object to assist in using CURIEs
//
// Shane McCarron, Applied Testing and Technology, Inc.
// Copyright 2008, All Rights Reserved.
//
// This source code is available under the license at:
//     http://www.w3.org/Consortium/Legal/copyright-software

var CURIE = {

    // maintain lists of attributes that can take CURIES.  In the real 
    // implementation when this whole thing is an object class, these should 
    // have accessor methods and be extensible

    _curieElms : [ "datatype", "typeof", "role", "rel", "rev", "property" ],

    _safeCurieElms : [ "about", "resource" ] ,

    // expand - expand one or more CURIEs in the context of a node
    //
    // returns a list of values if curies were passed in as an Array.
    // returns a string of space separated values otherwise.

    expand : function (node, curies, mappings) {
        if (node == null) return ;
        if (curies == null) return ;
        // no provided mappings - should we find some?
        if (mappings == null) {
            // this will handle both xmlns and @prefix
            mappings = CURIE._getPrefixMappings(node) ;
        }
        var retVals = [];
        // now expand the curies
        var wantArray = ( curies instanceof Array ) ;
        if (! wantArray ) 
            curies = curies.split(' ') ;
        for (var i=0; i < curies.length; i++) {
            if (curies[i].indexOf(':') > -1 ) {
                var items = curies[i].split(':', 2) ;
                if (mappings != null) {
                    if (mappings[items[0]]) {
                        curies[i] = mappings[items[0]] + items[1];
                    }
                }
            }
            retVals.push(curies[i]) ;
        }
        if (wantArray) {
            return retVals ;
        } else {
            return retVals.join(" ") ;
        }
    },

    // getAttrVal - get the values of an attribute expanding CURIES if appropriate
    //
    // returns a list of values

    getAttrVal: function (node, attr, mappings) {
        if (node == null) return ;
        if (attr == null) return ;

        var attrVal = node.getAttribute(attr) ;
        if (attrVal == null) return ;

        var vals = attrVal.split(' ') ;

        var ret = [] ;

        if (vals.length == 0) return ret ;
        
        // does this attribute take safe curies?
        var usesSafeCurie = 0;

        for (var i = 0; i < CURIE._safeCurieElms.length; i++) {
            if (CURIE._safeCurieElms[i] == attr) {
                usesSafeCurie = 1;
                break;
            }
        }
        if (!usesSafeCurie) {
            var usesCurie = 0 ;
            for (var i = 0; i < CURIE._curieElms.length; i++) {
                if (CURIE._curieElms[i] == attr) {
                    usesCurie = 1;
                    break;
                }
            }
            if (! usesCurie ) {
                // no CURIEs at all - just return the original data
                return vals;
            }
        }

        // we need to know the mappings
        if (mappings == null) mappings = CURIE._getPrefixMappings(node) ;

        for (var i = 0; i < vals.length; i++) {
            var expanded = "" ;
            if (usesSafeCurie) {
                if (vals[i].substr(0,1) == '[' && vals[i].substr(-1,1) == ']') {
                    // strip off the brackets and expand
                    expanded = CURIE.expand(node, vals[i].substr(1, ( vals[i].length-2 ) ), mappings) ;
                }
            } else {
                expanded = CURIE.expand(node, vals[i], mappings) ;
            }
            ret.push(expanded) ;
        }
        return ret ;
    },

    // Internal method - determine prefix mappings that are relevant
    // to a node.
    _getPrefixMappings : function (node) {
        var map = {} ;
        // walk up the tree getting all data from parent nodes
        if (node.nodeType != 1) return map ;
        var pNode = node.parentNode;

        if (pNode != null) {
            map = CURIE._getPrefixMappings(pNode) ;
        }
        if (node == null) return map ;
        var aList = node.attributes ;
        if (aList == null) return map ;
        for (var i=0; i < aList.length; i++) {
            var name = aList[i].name ;
            // there is an xmlns declaration
            if (name.indexOf('xmlns:') == 0) {
                var val = aList[i].value ;
                var item = name.substr(6) ;
                map[item] = val;
            }
            // there is a def using @prefix
            if (name == 'prefix') {
                var val = aList[i].value ;
                var prefixes = val.split(' ') ;
                for ( var j=0; i < prefixes.length; j++ ) {
                    var def = split('=', prefixes[j] ) ;
                    map[def[0]] = def[1] ;
                }
            }
        }
        return map ;
    }
};