/*****************************************************************************
* xmlparser.cpp
*****************************************************************************
- * Copyright (C) 2004 VideoLAN
+ * Copyright (C) 2004 the VideoLAN team
* $Id$
*
* Authors: Cyril Deguet <asmax@via.ecp.fr>
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "xmlparser.hpp"
+#include "../src/os_factory.hpp"
+#include <vlc_url.h>
-XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName ):
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName,
+ bool useDTD ):
SkinObject( pIntf )
{
- m_pReader = xmlNewTextReaderFilename( rFileName.c_str() );
+ m_pReader = NULL;
+ m_pStream = NULL;
+
+ if( useDTD )
+ {
+ m_pXML = xml_Create( pIntf );
+ if( m_pXML )
+ LoadCatalog();
+ else
+ {
+ msg_Err( getIntf(), "DTD not supported" );
+ useDTD = false;
+ }
+ }
+ else
+ m_pXML = NULL;
+
+ char* psz_uri = make_URI( rFileName.c_str(), NULL );
+ m_pStream = stream_UrlNew( pIntf, psz_uri );
+ free( psz_uri );
+
+ if( !m_pStream )
+ {
+ msg_Err( getIntf(), "failed to open %s for reading",
+ rFileName.c_str() );
+ return;
+ }
+ m_pReader = xml_ReaderCreate( m_pXML, m_pStream );
if( !m_pReader )
{
- msg_Err( getIntf(), "Failed to open %s for parsing",
+ 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 );
+ xml_ReaderUseDTD( m_pReader, useDTD );
}
XMLParser::~XMLParser()
{
- if( m_pReader )
- {
- xmlFreeTextReader( m_pReader );
- }
+ if( m_pReader ) xml_ReaderDelete( m_pReader );
+ if( m_pXML ) xml_Delete( m_pXML );
+ if( m_pStream ) stream_Delete( m_pStream );
}
-bool XMLParser::parse()
+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;
+
+#ifdef HAVE_SYS_STAT_H
+ 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++ )
{
- return false;
+ 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() )
+ {
+ // Ok, try the default one
+ xml_CatalogLoad( m_pXML, 0 );
}
- m_errors = false;
-
- int ret = xmlTextReaderRead( m_pReader );
- while (ret == 1)
+ for( it = resPath.begin(); it != resPath.end(); it++ )
{
- if( m_errors )
+ string path = (*it) + sep + "skin.dtd";
+ if( !stat( path.c_str(), &statBuf ) )
{
- return false;
+ // DTD found
+ msg_Dbg( getIntf(), "using DTD %s", path.c_str() );
+
+ // 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() )
+ {
+ msg_Err( getIntf(), "cannot find the skins DTD");
+ }
+#endif
+}
+
+bool XMLParser::parse()
+{
+ if( !m_pReader ) return false;
+
+ m_errors = false;
+
+ int ret = xml_ReaderRead( m_pReader );
+ while( ret == 1 )
+ {
+ 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 )
{
- const xmlChar *name = xmlTextReaderConstName( m_pReader );
- const xmlChar *value = xmlTextReaderConstValue( m_pReader );
+ char *name = xml_ReaderName( m_pReader );
+ char *value = xml_ReaderValue( m_pReader );
if( !name || !value )
{
+ free( name );
+ free( value );
return false;
}
- attributes[(const char*)name] = (const char*)value;
+ attributes[name] = value;
+ }
+
+ handleBeginElement( eltName, attributes );
+ free( eltName );
+
+ map<const char*, const char*, ltstr> ::iterator it =
+ attributes.begin();
+ while( it != attributes.end() )
+ {
+ free( (char *)it->first );
+ 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;
-}
-