xmlparser.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:6k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * xmlparser.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: dd7279b9b00017680c11ad84d3c6dc9d80a7b919 $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #include "xmlparser.hpp"
  24. #include "../src/os_factory.hpp"
  25. #ifdef HAVE_SYS_STAT_H
  26. #   include <sys/stat.h>
  27. #endif
  28. // Static variable to avoid initializing catalogs twice
  29. static bool m_initialized = false;
  30. XMLParser::XMLParser( intf_thread_t *pIntf, const string &rFileName,
  31.                       bool useDTD ):
  32.     SkinObject( pIntf )
  33. {
  34.     m_pReader = NULL;
  35.     m_pStream = NULL;
  36.     m_pXML = xml_Create( pIntf );
  37.     if( !m_pXML )
  38.     {
  39.         msg_Err( getIntf(), "failed to open XML parser" );
  40.         return;
  41.     }
  42.     // Avoid duplicate initialization (mutex needed ?) -> doesn't work
  43.     // Reinitialization required for a new XMLParser
  44.     // if( !m_initialized )
  45.     // {
  46.     //    LoadCatalog();
  47.     //    m_initialized = true;
  48.     // }
  49.     LoadCatalog();
  50.     m_pStream = stream_UrlNew( pIntf, rFileName.c_str() );
  51.     if( !m_pStream )
  52.     {
  53.         msg_Err( getIntf(), "failed to open %s for reading",
  54.                  rFileName.c_str() );
  55.         return;
  56.     }
  57.     m_pReader = xml_ReaderCreate( m_pXML, m_pStream );
  58.     if( !m_pReader )
  59.     {
  60.         msg_Err( getIntf(), "failed to open %s for parsing",
  61.                  rFileName.c_str() );
  62.         return;
  63.     }
  64.     xml_ReaderUseDTD( m_pReader, useDTD );
  65. }
  66. XMLParser::~XMLParser()
  67. {
  68.     if( m_pReader && m_pXML ) xml_ReaderDelete( m_pXML, m_pReader );
  69.     if( m_pXML ) xml_Delete( m_pXML );
  70.     if( m_pStream ) stream_Delete( m_pStream );
  71. }
  72. void XMLParser::LoadCatalog()
  73. {
  74.     // Get the resource path and look for the DTD
  75.     OSFactory *pOSFactory = OSFactory::instance( getIntf() );
  76.     const list<string> &resPath = pOSFactory->getResourcePath();
  77.     const string &sep = pOSFactory->getDirSeparator();
  78.     list<string>::const_iterator it;
  79. #ifdef HAVE_SYS_STAT_H
  80.     struct stat statBuf;
  81.     // Try to load the catalog first (needed at least on win32 where
  82.     // we don't have a default catalog)
  83.     for( it = resPath.begin(); it != resPath.end(); it++ )
  84.     {
  85.         string catalog_path = (*it) + sep + "skin.catalog";
  86.         if( !stat( catalog_path.c_str(), &statBuf ) )
  87.         {
  88.             msg_Dbg( getIntf(), "Using catalog %s", catalog_path.c_str() );
  89.             xml_CatalogLoad( m_pXML, catalog_path.c_str() );
  90.             break;
  91.         }
  92.     }
  93.     if( it == resPath.end() )
  94.     {
  95.         // Ok, try the default one
  96.         xml_CatalogLoad( m_pXML, 0 );
  97.     }
  98.     for( it = resPath.begin(); it != resPath.end(); it++ )
  99.     {
  100.         string path = (*it) + sep + "skin.dtd";
  101.         if( !stat( path.c_str(), &statBuf ) )
  102.         {
  103.             // DTD found
  104.             msg_Dbg( getIntf(), "using DTD %s", path.c_str() );
  105.             // Add an entry in the default catalog
  106.             xml_CatalogAdd( m_pXML, "public",
  107.                             "-//VideoLAN//DTD VLC Skins V"
  108.                             SKINS_DTD_VERSION "//EN", path.c_str() );
  109.             break;
  110.         }
  111.     }
  112.     if( it == resPath.end() )
  113.     {
  114.         msg_Err( getIntf(), "cannot find the skins DTD");
  115.     }
  116. #endif
  117. }
  118. bool XMLParser::parse()
  119. {
  120.     if( !m_pReader ) return false;
  121.     m_errors = false;
  122.     int ret = xml_ReaderRead( m_pReader );
  123.     while( ret == 1 )
  124.     {
  125.         if( m_errors ) return false;
  126.         // Get the node type
  127.         int type = xml_ReaderNodeType( m_pReader );
  128.         switch( type )
  129.         {
  130.             // Error
  131.             case -1:
  132.                 return false;
  133.                 break;
  134.             case XML_READER_STARTELEM:
  135.             {
  136.                 // Read the element name
  137.                 char *eltName = xml_ReaderName( m_pReader );
  138.                 if( !eltName ) return false;
  139.                 // Read the attributes
  140.                 AttrList_t attributes;
  141.                 while( xml_ReaderNextAttr( m_pReader ) == VLC_SUCCESS )
  142.                 {
  143.                     char *name = xml_ReaderName( m_pReader );
  144.                     char *value = xml_ReaderValue( m_pReader );
  145.                     if( !name || !value )
  146.                     {
  147.                         free( name );
  148.                         free( value );
  149.                         return false;
  150.                     }
  151.                     attributes[name] = value;
  152.                 }
  153.                 handleBeginElement( eltName, attributes );
  154.                 free( eltName );
  155.                 map<const char*, const char*, ltstr> ::iterator it =
  156.                     attributes.begin();
  157.                 while( it != attributes.end() )
  158.                 {
  159.                     free( (char *)it->first );
  160.                     free( (char *)it->second );
  161.                     it++;
  162.                 }
  163.                 break;
  164.             }
  165.             // End element
  166.             case XML_READER_ENDELEM:
  167.             {
  168.                 // Read the element name
  169.                 char *eltName = xml_ReaderName( m_pReader );
  170.                 if( !eltName ) return false;
  171.                 handleEndElement( eltName );
  172.                 free( eltName );
  173.                 break;
  174.             }
  175.         }
  176.         ret = xml_ReaderRead( m_pReader );
  177.     }
  178.     return (ret == 0 && !m_errors );
  179. }