]> git.sesse.net Git - vlc/blobdiff - modules/gui/skins2/parser/xmlparser.cpp
* ALL: New XML module type.
[vlc] / modules / gui / skins2 / parser / xmlparser.cpp
index a1dee471108d0e5481a2e9f245d96efa6018304a..37ff58e998dba7ebdd61be3ecffe15b17ead6e38 100644 (file)
  *****************************************************************************/
 
 #include "xmlparser.hpp"
+#include "../src/os_factory.hpp"
+
+#include <sys/stat.h>
+
+// Static variable to avoid initializing catalogs twice
+static bool m_initialized = false;
 
 XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName ):
     SkinObject( pIntf )
 {
-    m_pReader = xmlNewTextReaderFilename( rFileName.c_str() );
+    m_pXML = xml_Create( pIntf );
+    if( !m_pXML )
+    {
+        msg_Err( getIntf(), "Failed to open XML parser" );
+        m_pReader = NULL;
+        return;
+    }
+
+    // Avoid duplicate initialization (mutex needed ?)
+    if( !m_initialized )
+    {
+        LoadCatalog();
+        m_initialized = true;
+    }
+
+    m_pReader = xml_ReaderCreate( m_pXML, rFileName.c_str() );
     if( !m_pReader )
     {
         msg_Err( getIntf(), "Failed to open %s for parsing",
                  rFileName.c_str() );
         return;
     }
+}
 
-    // Activate DTD validation
-    xmlTextReaderSetParserProp( m_pReader, XML_PARSER_DEFAULTATTRS, 1 );
-    xmlTextReaderSetParserProp( m_pReader, XML_PARSER_VALIDATE, 1 );
 
-    // Set the error handler
-    xmlTextReaderSetErrorHandler( m_pReader, handleError, this );
+XMLParser::~XMLParser()
+{
+    if( m_pReader && m_pXML ) xml_ReaderDelete( m_pXML, m_pReader );
+    if( m_pXML ) xml_Delete( m_pXML );
 }
 
 
-XMLParser::~XMLParser()
+void XMLParser::LoadCatalog()
 {
-    if( m_pReader )
+    // Get the resource path and look for the DTD
+    OSFactory *pOSFactory = OSFactory::instance( getIntf() );
+    const list<string> &resPath = pOSFactory->getResourcePath();
+    const string &sep = pOSFactory->getDirSeparator();
+    list<string>::const_iterator it;
+    struct stat statBuf;
+
+    // Try to load the catalog first (needed at least on win32 where
+    // we don't have a default catalog)
+    for( it = resPath.begin(); it != resPath.end(); it++ )
+    {
+        string catalog_path = (*it) + sep + "skin.catalog";
+        if( !stat( catalog_path.c_str(), &statBuf ) )
+        {
+            msg_Dbg( getIntf(), "Using catalog %s", catalog_path.c_str() );
+            xml_CatalogLoad( m_pXML, catalog_path.c_str() );
+            break;
+        }
+    }
+    if( it == resPath.end() )
     {
-        xmlFreeTextReader( m_pReader );
+        // Ok, try the default one
+        xml_CatalogLoad( m_pXML, 0 );
     }
-}
 
+    for( it = resPath.begin(); it != resPath.end(); it++ )
+    {
+        string path = (*it) + sep + "skin.dtd";
+        if( !stat( path.c_str(), &statBuf ) )
+        {
+            // DTD found
+            msg_Dbg( getIntf(), "Using DTD %s", path.c_str() );
 
-bool XMLParser::parse()
-{
-    if( !m_pReader )
+            // Add an entry in the default catalog
+            xml_CatalogAdd( m_pXML, "public",
+                            "-//VideoLAN//DTD VLC Skins V"
+                            SKINS_DTD_VERSION "//EN", path.c_str() );
+            break;
+        }
+    }
+    if( it == resPath.end() )
     {
-        return false;
+        msg_Err( getIntf(), "Cannot find the skins DTD !");
     }
+}
+
+bool XMLParser::parse()
+{
+    if( !m_pReader ) return false;
 
     m_errors = false;
 
-    int ret = xmlTextReaderRead( m_pReader );
-    while (ret == 1)
+    int ret = xml_ReaderRead( m_pReader );
+    while( ret == 1 )
     {
-        if( m_errors )
-        {
-            return false;
-        }
+        if( m_errors ) return false;
+
         // Get the node type
-        int type = xmlTextReaderNodeType( m_pReader );
-        switch (type )
+        int type = xml_ReaderNodeType( m_pReader );
+        switchtype )
         {
             // Error
             case -1:
                 return false;
                 break;
 
-            // Begin element
-            case 1:
+            case XML_READER_STARTELEM:
             {
                 // Read the element name
-                const xmlChar *eltName = xmlTextReaderConstName( m_pReader );
-                if( !eltName )
-                {
-                    return false;
-                }
+                char *eltName = xml_ReaderName( m_pReader );
+                if( !eltName ) return false;
+
                 // Read the attributes
                 AttrList_t attributes;
-                while( xmlTextReaderMoveToNextAttribute( m_pReader ) == 1 )
+                while( xml_ReaderNextAttr( m_pReader ) == VLC_SUCCESS )
+                {
+                    char *name = xml_ReaderName( m_pReader );
+                    char *value = xml_ReaderValue( m_pReader );
+                    if( !name || !value ) return false;
+                    attributes[name] = value;
+                }
+
+                handleBeginElement( eltName, attributes );
+
+                map<const char*, const char*, ltstr> ::iterator it =
+                    attributes.begin();
+                while( it != attributes.end() )
                 {
-                    const xmlChar *name = xmlTextReaderConstName( m_pReader );
-                    const xmlChar *value = xmlTextReaderConstValue( m_pReader );
-                    if( !name || !value )
-                    {
-                        return false;
-                    }
-                    attributes[(const char*)name] = (const char*)value;
+                    free( (char *)it->second );
+                    it++;
                 }
-                handleBeginElement( (const char*)eltName, attributes);
                 break;
             }
 
             // End element
-            case 15:
+            case XML_READER_ENDELEM:
+            {
                 // Read the element name
-                const xmlChar *eltName = xmlTextReaderConstName( m_pReader );
-                if( !eltName )
-                {
-                    return false;
-                }
-                handleEndElement( (const char*)eltName );
+                char *eltName = xml_ReaderName( m_pReader );
+                if( !eltName ) return false;
+
+                handleEndElement( eltName );
+                free( eltName );
                 break;
+            }
         }
-        ret = xmlTextReaderRead( m_pReader );
+        ret = xml_ReaderRead( m_pReader );
     }
     return (ret == 0 && !m_errors );
 }
-
-
-void XMLParser::handleError( void *pArg,  const char *pMsg,
-                             xmlParserSeverities severity,
-                             xmlTextReaderLocatorPtr locator)
-{
-    XMLParser *pThis = (XMLParser*)pArg;
-    int line = xmlTextReaderLocatorLineNumber( locator );
-    msg_Err( pThis->getIntf(), "XML parser error (line %d) : %s", line, pMsg );
-    pThis->m_errors = true;
-}