コード例 #1
0
ファイル: ejsXML.c プロジェクト: embedthis/ejscript
/*
    Lookup a property by name. There are 7 kinds of lookups:
         prop, @att, [prop], *, @*, .name, .@name
 */
static EjsObj *getXmlPropertyByName(Ejs *ejs, EjsXML *xml, EjsName qname)
{
    EjsXML      *item, *result, *list;
    int         next, nextList;

    result = 0;

    assert(xml->kind < 5);
    if (isdigit((uchar) qname.name->value[0]) && allDigitsForXml(qname.name)) {
        /*
            Consider xml as a list with only one entry == xml. Then return the 0'th entry
         */
        return (EjsObj*) xml;
    }

    if (qname.name->value[0] == '@') {
        /* @ and @* */
        result = ejsCreateXMLList(ejs, xml, qname);
        if (xml->attributes) {
            for (next = 0; (item = mprGetNextItem(xml->attributes, &next)) != 0; ) {
                assert(qname.name->value[0] == '@');
                if (qname.name->value[1] == '*' || wcmp(item->qname.name->value, &qname.name->value[1]) == 0) {
                    result = ejsAppendToXML(ejs, result, item);
                }
            }
        }

    } else if (qname.name->value[0] == '.') {
        /* Decenders (do ..@ also) */
        result = ejsGetXMLDescendants(ejs, xml, qname);

    } else {
        /* name and * */
        result = ejsCreateXMLList(ejs, xml, qname);
        if (xml->elements) {
            for (next = 0; (item = mprGetNextItem(xml->elements, &next)) != 0; ) {
                if (item->kind == EJS_XML_LIST) {
                    list = item;
                    for (nextList = 0; (item = mprGetNextItem(list->elements, &nextList)) != 0; ) {
                        assert(item->qname.name);
                        if (qname.name->value[0] == '*' || ejsCompareString(ejs, item->qname.name, qname.name) == 0) {
                            result = ejsAppendToXML(ejs, result, item);
                        }
                    }

                } else if (item->qname.name) {
                    assert(item->qname.name);
                    if (qname.name->value[0] == '*' || ejsCompareString(ejs, item->qname.name, qname.name) == 0) {
                        result = ejsAppendToXML(ejs, result, item);
                    }
                }
            }
        }
    }
    return (EjsObj*) result;
}
コード例 #2
0
ファイル: ejsXML.c プロジェクト: embedthis/ejscript
/*
    Create a value node. If the value is an XML node already, we are done. Otherwise, cast the value to a string
    and create a text child node containing the string value.
 */
static EjsXML *createValueNode(Ejs *ejs, EjsXML *elt, EjsObj *value)
{
    EjsXML      *text;
    EjsString   *str;

    if (ejsIsXML(ejs, value)) {
        return (EjsXML*) value;
    }
    if ((str = (EjsString*) ejsCast(ejs, value, String)) == NULL) {
        return 0;
    }
    if (mprGetListLength(elt->elements) == 1) {
        /*
            Update an existing text element
         */
        text = mprGetFirstItem(elt->elements);
        if (text->kind == EJS_XML_TEXT) {
            text->value = str;
            return elt;
        }
    }

    /*
        Create a new text element
     */
    if (str->value[0] != '\0') {
        text = ejsCreateXML(ejs, EJS_XML_TEXT, N(NULL, NULL), elt, str);
        elt = ejsAppendToXML(ejs, elt, text);
    }
    return elt;
}
コード例 #3
0
ファイル: ejsXMLList.c プロジェクト: monmarzia/ejs-2
/*
    Lookup a property by name. There are 7 kinds of lookups:
         prop, @att, [prop], *, @*, .name, .@name
 */
static EjsObj *getXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname)
{
    EjsXML      *result, *subList, *item;
    int         nextItem;

    /*
        Get the n'th item in the list
     */
    if (isdigit((uchar) qname.name->value[0]) && allDigitsForXmlList(qname.name)) {
        return mprGetItem(list->elements, ejsAtoi(ejs, qname.name, 10));
    }

    result = ejsCreateXMLList(ejs, list, qname);

    /*
        Build a list of all the elements that themselves have a property qname
     */
    for (nextItem = 0; (item = mprGetNextItem(list->elements, &nextItem)) != 0; ) {
        if (item->kind == EJS_XML_ELEMENT) {
            subList = ejsGetPropertyByName(ejs, (EjsObj*) item, qname);
            assure(ejsIsXML(ejs, subList));
            ejsAppendToXML(ejs, result, subList);

        } else {
            //  TODO - do we ever get a list in a list?
            assure(0);
        }
    }
    return (EjsObj*) result;
}
コード例 #4
0
ファイル: ejsXML.c プロジェクト: embedthis/ejscript
PUBLIC EjsXML *ejsGetXMLDescendants(Ejs *ejs, EjsXML *xml, EjsName qname)
{
    EjsXML          *item, *result;
    int             next;

    result = ejsCreateXMLList(ejs, xml, qname);
    if (result == 0) {
        return 0;
    }
    if (qname.name->value[0] == '.' && qname.name->value[1] == '@') {
        if (xml->attributes) {
            for (next = 0; (item = mprGetNextItem(xml->attributes, &next)) != 0; ) {
                if (qname.name->value[2] == '*' || wcmp(item->qname.name->value, &qname.name->value[2]) == 0) {
                    result = ejsAppendToXML(ejs, result, item);
                }
            }
        }
        if (xml->elements) {
            for (next = 0; (item = mprGetNextItem(xml->elements, &next)) != 0; ) {
                result = ejsAppendToXML(ejs, result, ejsGetXMLDescendants(ejs, item, qname));
            }
        }

    } else {
        if (xml->elements) {
            for (next = 0; (item = mprGetNextItem(xml->elements, &next)) != 0; ) {
                if (qname.name->value[0] == '*' || wcmp(item->qname.name->value, &qname.name->value[1]) == 0) {
                    result = ejsAppendToXML(ejs, result, item);
                } else {
                    result = ejsAppendToXML(ejs, result, ejsGetXMLDescendants(ejs, item, qname));
                }
            }
        }
    }
    return result;
}
コード例 #5
0
ファイル: ejsXMLList.c プロジェクト: monmarzia/ejs-2
/*
    Set an alpha property by name.
 */
static int setAlphaPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname, EjsObj *value)
{
    EjsXML      *elt, *targetObject;
    int         count;

    targetObject = 0;

    count = ejsGetLength(ejs, (EjsObj*) list);
    if (count > 1) {
        //  TODO - why no error in spec?
        assure(0);
        return 0;
    }

    if (count == 0) {
        /*
            Empty list so resolve the real target object and append it to the list.
         */
        targetObject = resolve(ejs, list);
        if (targetObject == 0) {
            return 0;
        }
        if (ejsGetLength(ejs, (EjsObj*) targetObject) != 1) {
            return 0;
        }
        ejsAppendToXML(ejs, list, targetObject);
    }

    /*
        Update the element
     */
    assure(ejsGetLength(ejs, (EjsObj*) list) == 1);
    elt = mprGetItem(list->elements, 0);                        //  TODO OPT - GetFirstItem
    assure(elt);
    ejsSetPropertyByName(ejs, elt, qname, value);
    return 0;
}
コード例 #6
0
ファイル: ejsXMLLoader.c プロジェクト: embedthis/ejs-1
static int parserHandler(MprXml *xp, int state, cchar *tagName, cchar *attName, cchar *value)
{
    Ejs             *ejs;
    EjsXmlState     *parser;
    EjsXmlTagState  *tos;
    EjsName         qname;
    EjsXML          *xml, *node, *parent;

    parser = (EjsXmlState*) xp->parseArg;
    ejs = parser->ejs;
    tos = &parser->nodeStack[parser->topOfStack];
    xml = tos->obj;
    
    mprAssert(xml);

    mprAssert(state >= 0);
    mprAssert(tagName && *tagName);

    switch (state) {
    case MPR_XML_PI:
        node = ejsCreateXML(ejs, EJS_XML_PROCESSING, NULL, xml, value);
        ejsAppendToXML(ejs, xml, node);
        break;

    case MPR_XML_COMMENT:
        node = ejsCreateXML(ejs, EJS_XML_COMMENT, NULL, xml, value);
        ejsAppendToXML(ejs, xml, node);
        break;

    case MPR_XML_NEW_ELT:
        if (parser->topOfStack > E4X_MAX_NODE_DEPTH) {
            ejsThrowSyntaxError(ejs,  "XML nodes nested too deeply in %s at line %d", parser->filename, 
                mprXmlGetLineNumber(xp));
            return MPR_ERR_BAD_SYNTAX;
        }
        if (xml->kind <= 0) {
            ejsConfigureXML(ejs, xml, EJS_XML_ELEMENT, tagName, xml, NULL);
        } else {
            ejsName(&qname, 0, tagName);
            xml = ejsCreateXML(ejs, EJS_XML_ELEMENT, &qname, xml, NULL);
            tos = &parser->nodeStack[++(parser->topOfStack)];
            tos->obj = (EjsXML*) xml;
            tos->attributes = 0;
            tos->comments = 0;
        }
        break;

    case MPR_XML_NEW_ATT:
        ejsName(&qname, 0, attName);
        node = ejsCreateXML(ejs, EJS_XML_ATTRIBUTE, &qname, xml, value);
        ejsAppendAttributeToXML(ejs, xml, node);
        break;

    case MPR_XML_SOLO_ELT_DEFINED:
        if (parser->topOfStack > 0) {
            parent = parser->nodeStack[parser->topOfStack - 1].obj;
            ejsAppendToXML(ejs, parent, xml);
            parser->topOfStack--;
            mprAssert(parser->topOfStack >= 0);
            tos = &parser->nodeStack[parser->topOfStack];
        }
        break;

    case MPR_XML_ELT_DEFINED:
        if (parser->topOfStack > 0) {
            parent = parser->nodeStack[parser->topOfStack - 1].obj;
            ejsAppendToXML(ejs, parent, xml);
        }
        break;

    case MPR_XML_ELT_DATA:
    case MPR_XML_CDATA:
        ejsName(&qname, 0, attName);
        node = ejsCreateXML(ejs, EJS_XML_TEXT, &qname, xml, value);
        ejsAppendToXML(ejs, xml, node);
        break;

    case MPR_XML_END_ELT:
        /*
         *  This is the closing element in a pair "<x>...</x>".
         *  Pop the stack frame off the elt stack
         */
        if (parser->topOfStack > 0) {
            parser->topOfStack--;
            mprAssert(parser->topOfStack >= 0);
            tos = &parser->nodeStack[parser->topOfStack];
        }
        break;

    default:
        ejsThrowSyntaxError(ejs, "XML error in %s at %d\nDetails %s", parser->filename, mprXmlGetLineNumber(xp), 
            mprXmlGetErrorMsg(xp));
        mprAssert(0);
        return MPR_ERR_BAD_SYNTAX;
    }
    return 0;
}
コード例 #7
0
ファイル: ejsXML.c プロジェクト: embedthis/ejscript
/*
    Set a property by name
    There are 7 kinds of qname's: prop, @att, [prop], *, @*, .name, .@name
 */
static int setXmlPropertyByName(Ejs *ejs, EjsXML *xml, EjsName qname, EjsObj *value)
{
    EjsXML      *elt, *xvalue, *rp, *lastElt;
    EjsObj      *originalValue;
    int         index, last;

    last = 0;
    lastElt = 0;

    if (isdigit((uchar) qname.name->value[0]) && allDigitsForXml(qname.name)) {
        ejsThrowTypeError(ejs, "Integer indicies for set are not allowed");
        return EJS_ERR;
    }

    if (xml->kind != EJS_XML_ELEMENT) {
        //  TODO spec requires this -- but why? -- surely throw?
        return 0;
    }

    /*
        Massage the value type.
     */
    originalValue = value;

    xvalue = (EjsXML*) value;
    if (ejsIsXML(ejs, xvalue)) {
        if (xvalue->kind == EJS_XML_LIST) {
            value = cloneXml(ejs, xvalue, 1);

        } else if (xvalue->kind == EJS_XML_TEXT || xvalue->kind == EJS_XML_ATTRIBUTE) {
            value = ejsCast(ejs, originalValue, String);

        } else {
            value = cloneXml(ejs, xvalue, 1);
        }
    } else {
        value = ejsCast(ejs, value, String);
    }
    if (qname.name->value[0] == '@') {
        return setXmlPropertyAttributeByName(ejs, xml, qname, value);
    }
    /*
        Delete redundant elements by the same name.
     */
    if (xml->elements) {
        for (last = -1, index = -1; (elt = mprGetPrevItem(xml->elements, &index)) != 0; ) {
            if (qname.name->value[0] == '*' || (elt->kind == EJS_XML_ELEMENT && elt->qname.name == qname.name)) {
                /*
                    Must remove all redundant elements of the same name except the first one
                 */
                if (last >= 0) {
                    rp = mprGetItem(xml->elements, last);
                    rp->parent = 0;
                    mprRemoveItemAtPos(xml->elements, last);
                }
                last = index;
                lastElt = elt;
            }
        }
    }
    if (xml->elements == 0) {
        //  TODO - need routine to do this centrally so we can control the default number of elements in the list?
        xml->elements = mprCreateList(-1, 0);
    }
    elt = lastElt;
    index = last;

    if (qname.name->value[0] == '*') {
        /*
            Special case when called from XMLList to update the value of an element
         */
        xml = createValueNode(ejs, xml, value);

    } else if (elt == 0) {
        /*
            Not found. New node required.
         */
        elt = ejsCreateXML(ejs, EJS_XML_ELEMENT, qname, xml, NULL);
        if (elt == 0) {
            return 0;
        }
        index = mprGetListLength(xml->elements);
        xml = ejsAppendToXML(ejs, xml, createValueNode(ejs, elt, value));

    } else {
        /*
            Update existing element.
         */
        xml = ejsSetXMLElement(ejs, xml, index, createValueNode(ejs, elt, value));
    }

    if (xml == 0) {
        return EJS_ERR;
    }
    return index;
}