📄 ejsxml.c
字号:
/* * @file ejsXml.c * @brief E4X XML support *//********************************* Copyright **********************************//* * @copy default * * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. * * This software is distributed under commercial and open source licenses. * You may use the GPL open source license described below or you may acquire * a commercial license from Mbedthis Software. You agree to be fully bound * by the terms of either license. Consult the LICENSE.TXT distributed with * this software for full details. * * This software is open source; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See the GNU General Public License for more * details at: http://www.mbedthis.com/downloads/gplLicense.html * * This program is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * This GPL license does NOT permit incorporating this software into * proprietary programs. If you are unable to comply with the GPL, you must * acquire a commercial license to use this software. Commercial licenses * for this software and support services are available from Mbedthis * Software at http://www.mbedthis.com * * @end *//************************************ Doc *************************************//* * Javascript class definition * * class XML { * public XML(); * public XML(string xmlString); // "<tag... " * public XML(string file); // "file" * * public void load(string file); * public void save(string file); * public Array children(); * public Array attributes(); * } * [[Internal Properties / Methods]] - prototype - Ptr to class prototype (base class) - class - Type of class Object.prototype.toString - Value - - Get(name) - Returns the value - Put(name, value) - Sets the value - HasProperty(name) - Bool if property exists - Delete(name) - Delete property - DefaultValue(hint) - Return default primitive (not obj) value toString, if result is obj, then call valueOf if hint is number, then call valueOf, then toString - Construct(arg list) - Constructor - Call(arg list) - Function call - HasInstance(value) - ?? - Scope - Frame scope chain - Match(string, index) - Regexp match - Example: XML attribute @name @* * var node = new XML("<order/>"); Operators: var prices = order..price; var urgentItems = order.item(@level == "rush"); var itemAttrs = order.item[0].@*; # @ for attributes XML Literals order.customer.address = <address>..... <zip>{zipCode}</zip> Where {var} is a JS var <tag attribute={prefix}> ... Also for attributes </address> Omit namespaces Example: var html = <html/>; html.head.title = "My title"; head.body@bgcolor = "#e4e4e4";*//********************************** Includes **********************************/#include "ejs.h"#include "exml.h"/************************************ Data ************************************/#if BLD_FEATURE_EJS_E4X/* * Per tag state */typedef struct XmlTagState { EjsVar *obj; EjsVar *attributes; EjsVar *comments;} XmlTagState;/* * Parser state */typedef struct XmlState { Ejs *ep; EjsVar *xmlClass; EjsVar *xmlListClass; XmlTagState nodeStack[E4X_MAX_NODE_DEPTH]; int topOfStack; long inputSize; long inputPos; const char *inputBuf; const char *fileName;} XmlState;/****************************** Forward Declarations **************************//* * XML methods */static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int name(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int save(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int toString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int valueOf(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);/* MOB -- temp */static int getList(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int setText(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);#if FUTUREstatic int length(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int toXmlString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int appendChild(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int attributes(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int child(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int children(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int comments(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int decendants(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int elements(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int insertChildAfter(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int insertChildBefore(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int replace(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int setName(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv);#endif/* * Internal methods */static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property);static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property);static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property);static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property, const EjsVar *value);static int loadXmlString(Ejs *ep, EjsVar *thisObj, const char *xmlString);/* * XMLList methods */static EjsVar *createXmlListProperty(Ejs *ep, EjsVar *obj, const char *property);static int deleteXmlListProperty(Ejs *ep, EjsVar *obj, const char *property);static EjsVar *getXmlListProperty(Ejs *ep, EjsVar *obj, const char *property);static EjsVar *setXmlListProperty(Ejs *ep, EjsVar *obj, const char *property, const EjsVar *value);/* * Misc */static int readFileData(Exml *xp, void *data, char *buf, int size);static int readStringData(Exml *xp, void *data, char *buf, int size);static int parserHandler(Exml *xp, int state, const char *tagName, const char *attName, const char *value);static void termParser(Exml *xp);static Exml *initParser(Ejs *ep, EjsVar *thisObj, const char *fileName);static int getNumElements(EjsVar *obj);static int getText(MprBuf *buf, EjsVar *obj);static int xmlToString(Ejs *ep, MprBuf *buf, EjsVar *obj, int indentLevel);static void indent(MprBuf *bp, int level);static char *cleanTagName(char *name);/******************************************************************************//* * Define the E4X classes (XML, XMLList) */int ejsDefineXmlClasses(Ejs *ep){ EjsMethods *methods; EjsVar *xmlClass, *xmlListClass; /* * Create the XML class */ xmlClass = ejsDefineClass(ep, "XML", "Object", ejsXmlConstructor); if (xmlClass == 0) { return MPR_ERR_CANT_INITIALIZE; } /* * Define the XML class methods */ ejsDefineCMethod(ep, xmlClass, "text", text, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "name", name, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "load", load, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "save", save, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "toString", toString, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "valueOf", valueOf, EJS_NO_LOCAL);/* MOB -- temporary only */ ejsDefineCMethod(ep, xmlClass, "getList", getList, EJS_NO_LOCAL); ejsDefineCMethod(ep, xmlClass, "setText", setText, EJS_NO_LOCAL); /* * Setup the XML internal methods. */ methods = mprAllocTypeZeroed(ep, EjsMethods); xmlClass->objectState->methods = methods; methods->createProperty = createXmlProperty; methods->deleteProperty = deleteXmlProperty; methods->getProperty = getXmlProperty; methods->setProperty = setXmlProperty; /* * Create the XMLList class */ xmlListClass = ejsDefineClass(ep, "XMLList", "Array", ejsXmlListConstructor); /* * Define the XMLList class methods */ /* * Setup the XML internal methods. */ methods = mprAllocTypeZeroed(ep, EjsMethods); xmlListClass->objectState->methods = methods; methods->createProperty = createXmlListProperty; methods->deleteProperty = deleteXmlListProperty; methods->getProperty = getXmlListProperty; methods->setProperty = setXmlListProperty; /* MOB -- need to complete xmlListClass */ return (ejsObjHasErrors(xmlClass) || ejsObjHasErrors(xmlListClass)) ? MPR_ERR_CANT_INITIALIZE : 0; return 0;}/******************************************************************************//* * Routine to create an XML object using a default constructor */EjsVar *ejsCreateXml(Ejs *ep){ EjsVar *op; op = ejsCreateSimpleObj(ep, "XML"); if (op == 0) { mprAssert(op); return op; } ejsSetVarName(ep, op, "xmlNode"); /* * Invoke class constructors manually (for speed and space) */ if (ejsXmlConstructor(ep, op, 0, 0) < 0) { mprFree(op); mprAssert(0); return 0; } return op;}/******************************************************************************//* * XML constructor */int ejsXmlConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv){ EjsVar *vp; const char *str; ejsSetVarFlags(thisObj, EJS_XML_FLAGS_ELEMENT); if (argc == 1) { vp = argv[0]; if (ejsVarIsObject(vp)) { /* Convert DOM to XML. Not implemented */; } else if (ejsVarIsString(vp)) { str = vp->string; if (str == 0) { return 0; } if (*str == '<') { /* XML Literal */ return loadXmlString(ep, thisObj, str); } else { /* Load from file */ return load(ep, thisObj, argc, argv); } } else { ejsError(ep, EJS_TYPE_ERROR, "Bad type passed to XML constructor"); return -1; } } return 0;}/******************************************************************************//* * Routine to create an XMLList object */EjsVar *ejsCreateXmlList(Ejs *ep){ EjsVar *op; /* Sanity limit for size of hash table */ op = ejsCreateSimpleObj(ep, "XMLList"); if (op == 0) { mprAssert(0); return op; } if (ejsArrayConstructor(ep, op, 0, 0) < 0 || ejsXmlConstructor(ep, op, 0, 0) < 0) { mprFree(op); mprAssert(0); return 0; } return op;}/******************************************************************************//* * XMLList constructor */int ejsXmlListConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv){ // ejsSetVarFlags(vp, EJS_XML_FLAGS_ELEMENT); return 0;}/******************************************************************************//******************************** Internal Methods ****************************//******************************************************************************/static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property){ return ejsGetVarPtr(ejsCreateSimpleProperty(ep, obj, property));}/******************************************************************************/static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property){ return ejsDeleteProperty(ep, obj, property);}/******************************************************************************//* MOB -- need ep as an arg */static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property){#if NEW EjsVar *lp; lp = ejsCreateXmlList(ep); if (isdigit(*property)) { /* MOB -- where do we store these. Do we need them ? */ lp->targetObject = obj lp->targetProperty = property return getXmlListProperty(lp, property); } /* What about a simple elment. Should it not return the text */ if (*property == '@') { ap = ejsGetFirstProperty(obj, EJS_ENUM_ALL); while (ap) { vp = ejsGetVarPtr(ap); /* MOB -- are attributes unique ? */ if (vp->flags & EJS_XML_FLAGS_ATTRIBUTE && strcmp(property, ap->name) == 0) { ejsAppendXml(lp, vp); } ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL); } } else { while (ap) { vp = ejsGetVarPtr(ap); /* MOB -- are attributes unique ? */ if (vp->flags & EJS_XML_FLAGS_ELEMENT && strcmp(property, ap->name) == 0) { ejsAppendXml(lp, vp); } ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL); } } return l; // Must always return XML or XMLList event for comments and attributes#endif return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property));}/******************************************************************************/static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property, const EjsVar *value){ EjsProperty *pp; EjsVar *vp; pp = ejsCreateSimpleProperty(ep, obj, property); if (pp == 0) { /* Should never happen */ mprAssert(pp); return 0; } vp = ejsGetVarPtr(pp); if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0) { return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -