*****************************************************************************/
#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 );
+ switch( type )
{
// 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;
-}
-