VirtualBox

Changeset 7309 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 5, 2008 5:47:51 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
28715
Message:

Main/Settings: Added XSLT-based auto-conversion functionality to the XmlTree backend.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r6988 r7309  
    407407VBoxSettings_TEMPLATE   = VBOXMAINDLL
    408408VBoxSettings_NAME       = $(basename $(notdir $(LIB_SETTINGS)))
    409 VBoxSettings_SDKS       = VBOX_LIBXML2 VBOX_ZLIB
     409VBoxSettings_SDKS       = VBOX_LIBXSLT VBOX_LIBXML2 VBOX_ZLIB
    410410VBoxSettings_DEFS       = IN_VBOXSETTINGS_R3
    411411VBoxSettings_INCS       = \
  • trunk/src/VBox/Main/xml/Settings.cpp

    r7027 r7309  
    3030
    3131#include <libxml/xmlschemas.h>
     32
     33#include <libxslt/xsltInternals.h>
     34#include <libxslt/transform.h>
     35#include <libxslt/xsltutils.h>
    3236
    3337#include <string.h>
     
    804808    std::auto_ptr <stdx::exception_trap_base> trappedErr;
    805809
     810    struct AutoConv
     811    {
     812        AutoConv() : root (NULL), attr (NULL), version (NULL), xslt (NULL) {}
     813        ~AutoConv() { uninit(); }
     814
     815        void uninit()
     816        {
     817            RTStrFree (xslt); xslt = NULL;
     818            RTStrFree (version); version = NULL;
     819            RTStrFree (attr); attr = NULL;
     820            RTStrFree (root); root = NULL;
     821        }
     822
     823        bool isNull() { return xslt == NULL; }
     824
     825        char *root;
     826        char *attr;
     827        char *version;
     828        char *xslt;
     829    }
     830    autoConv;
     831
    806832    /**
    807833     * This is to avoid throwing exceptions while in libxml2 code and
     
    870896}
    871897
     898void XmlTreeBackend::setAutoConversion (const char *aRoot, const char *aAttr,
     899                                        const char *aVersion, const char *aTemplate)
     900{
     901    if (aRoot == NULL && aAttr == NULL && aVersion == NULL && aTemplate == NULL)
     902    {
     903        m->autoConv.uninit();
     904        return;
     905    }
     906
     907    if (aRoot == NULL || aAttr == NULL || aVersion == NULL || aTemplate == NULL)
     908        throw EInvalidArg (RT_SRC_POS);
     909
     910    m->autoConv.root = RTStrDup (aRoot);
     911    m->autoConv.attr = RTStrDup (aAttr);
     912    m->autoConv.version = RTStrDup (aVersion);
     913    m->autoConv.xslt = RTStrDup (aTemplate);
     914}
     915
    872916void XmlTreeBackend::rawRead (Input &aInput, const char *aSchema /* = NULL */,
    873917                              int aFlags /* = 0 */)
     
    876920     * libxml2 code. */
    877921    m->trappedErr.reset();
    878 
    879     /* Set up an input stream for parsing the document. This will be deleted
    880      * when the stream is closed by the libxml2 API (e.g. when calling
    881      * xmlFreeParserCtxt()). */
    882     Data::InputCtxt *inputCtxt =
    883         new Data::InputCtxt (&aInput, m->trappedErr);
    884922
    885923    /* Set up the external entity resolver. Note that we do it in a
     
    899937
    900938    /* parse the stream */
     939    /* NOTE: new InputCtxt instance will be deleted when the stream is closed by
     940     * the libxml2 API (e.g. when calling xmlFreeParserCtxt()) */
    901941    xmlDocPtr doc = xmlCtxtReadIO (m->ctxt,
    902942                                   ReadCallback, CloseCallback,
    903                                    inputCtxt, aInput.uri(), NULL,
     943                                   new Data::InputCtxt (&aInput, m->trappedErr),
     944                                   aInput.uri(), NULL,
    904945                                   XML_PARSE_NOBLANKS);
    905946    if (doc == NULL)
     
    916957    }
    917958
     959    /* perform automatic document transformation if necessary */
     960    if (!m->autoConv.isNull())
     961    {
     962        Key root = Key (new XmlKeyBackend (xmlDocGetRootElement (doc)));
     963        if (!strcmp (root.name(), m->autoConv.root))
     964        {
     965            const char *ver = root.stringValue (m->autoConv.attr);
     966            if (strcmp (ver, m->autoConv.version))
     967            {
     968                /* version mismatch */
     969
     970                xmlDocPtr xsltDoc = NULL;
     971                xsltStylesheetPtr xslt = NULL;
     972                xsltTransformContextPtr tranCtxt = NULL;
     973                char *errorStr = NULL;
     974
     975                try
     976                {
     977                    /* parse the XSLT */
     978                    {
     979                        Input *xsltInput =
     980                            m->inputResolver->resolveEntity (m->autoConv.xslt, NULL);
     981                        /* NOTE: new InputCtxt instance will be deleted when the
     982                         * stream is closed by the libxml2 API */
     983                        xsltDoc = xmlCtxtReadIO (m->ctxt,
     984                                                 ReadCallback, CloseCallback,
     985                                                 new Data::InputCtxt (xsltInput, m->trappedErr),
     986                                                 m->autoConv.xslt, NULL,
     987                                                 0);
     988                        delete xsltInput;
     989                    }
     990
     991                    if (xsltDoc == NULL)
     992                    {
     993                        /* look if there was a forwared exception from the lower level */
     994                        if (m->trappedErr.get() != NULL)
     995                            m->trappedErr->rethrow();
     996
     997                        throw XmlError (xmlCtxtGetLastError (m->ctxt));
     998                    }
     999
     1000                    xslt = xsltParseStylesheetDoc (xsltDoc);
     1001                    if (xslt == NULL)
     1002                        throw LogicError (RT_SRC_POS);
     1003
     1004                    /* setup transformation error reporting */
     1005                    tranCtxt = xsltNewTransformContext (xslt, xsltDoc);
     1006                    if (tranCtxt == NULL)
     1007                        throw LogicError (RT_SRC_POS);
     1008                    xsltSetTransformErrorFunc (tranCtxt, &errorStr, ValidityErrorCallback);
     1009
     1010                    xmlDocPtr newDoc = xsltApplyStylesheetUser (xslt, doc, NULL,
     1011                                                                NULL, NULL, tranCtxt);
     1012                    if (newDoc == NULL)
     1013                        throw LogicError (RT_SRC_POS);
     1014
     1015                    if (errorStr != NULL)
     1016                    {
     1017                        xmlFreeDoc (newDoc);
     1018                        throw Error (errorStr);
     1019                        /* errorStr is freed in catch(...) below */
     1020                    }
     1021
     1022                    /* replace the old document on success */
     1023                    xmlFreeDoc (doc);
     1024                    doc = newDoc;
     1025
     1026                    xsltFreeTransformContext (tranCtxt);
     1027
     1028                    /* NOTE: xsltFreeStylesheet() also fress the document
     1029                     * passed to xsltParseStylesheetDoc(). */
     1030                    xsltFreeStylesheet (xslt);
     1031                }
     1032                catch (...)
     1033                {
     1034                    /* restore the previous entity resolver */
     1035                    xmlSetExternalEntityLoader (oldEntityLoader);
     1036                    sThat = NULL;
     1037
     1038                    RTStrFree (errorStr);
     1039
     1040                    if (tranCtxt != NULL)
     1041                        xsltFreeTransformContext (tranCtxt);
     1042
     1043                    /* NOTE: xsltFreeStylesheet() also fress the document
     1044                     * passed to xsltParseStylesheetDoc(). */
     1045                    if (xslt != NULL)
     1046                        xsltFreeStylesheet (xslt);
     1047                    else if (xsltDoc != NULL)
     1048                        xmlFreeDoc (xsltDoc);
     1049
     1050                    throw;
     1051                }
     1052            }
     1053        }
     1054    }
     1055
     1056    /* validate the document */
    9181057    if (aSchema != NULL)
    9191058    {
     
    9231062        char *errorStr = NULL;
    9241063
    925         /* validate the document */
    9261064        try
    9271065        {
     
    11611299        -- newMsgLen;
    11621300
    1163     if (str == NULL)
    1164     {
    1165         str = newMsg;
    1166         newMsg [newMsgLen] = '\0';
    1167     }
    1168     else
    1169     {
    1170         /* append to the existing string */
    1171         size_t strLen = strlen (str);
    1172         char *newStr = (char *) RTMemRealloc (str, strLen + 2 + newMsgLen + 1);
    1173         AssertReturnVoid (newStr != NULL);
    1174 
    1175         memcpy (newStr + strLen, ".\n", 2);
    1176         memcpy (newStr + strLen + 2, newMsg, newMsgLen);
    1177         newStr [strLen + 2 + newMsgLen] = '\0';
    1178         str = newStr;
    1179         RTStrFree (newMsg);
     1301    /* anything left? */
     1302    if (newMsgLen > 0)
     1303    {
     1304        if (str == NULL)
     1305        {
     1306            str = newMsg;
     1307            newMsg [newMsgLen] = '\0';
     1308        }
     1309        else
     1310        {
     1311            /* append to the existing string */
     1312            size_t strLen = strlen (str);
     1313            char *newStr = (char *) RTMemRealloc (str, strLen + 2 + newMsgLen + 1);
     1314            AssertReturnVoid (newStr != NULL);
     1315
     1316            memcpy (newStr + strLen, ".\n", 2);
     1317            memcpy (newStr + strLen + 2, newMsg, newMsgLen);
     1318            newStr [strLen + 2 + newMsgLen] = '\0';
     1319            str = newStr;
     1320            RTStrFree (newMsg);
     1321        }
    11801322    }
    11811323}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette