Reader.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 extern "C"
00013 {
00014 #include <libxml/xmlreader.h>
00015 #include <libxml/xmlerror.h>
00016 }
00017 
00018 #include <iostream>
00019 
00020 #include "zypp/base/LogControl.h"
00021 #include "zypp/base/LogTools.h"
00022 #include "zypp/base/Exception.h"
00023 
00024 #include "zypp/parser/xml/Reader.h"
00025 
00026 using std::endl;
00027 
00029 namespace zypp
00030 { 
00031 
00032   namespace xml
00033   { 
00034 
00036     namespace
00037     { 
00038 
00039       int ioread( void * context_r, char * buffer_r, int bufferLen_r )
00040       {
00041         if ( context_r && buffer_r )
00042           {
00043             return reinterpret_cast<InputStream *>(context_r)
00044                    ->stream().read( buffer_r, bufferLen_r ).gcount();
00045           }
00046         INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl;
00047         return -1;
00048       }
00049 
00050       int ioclose( void * /*context_r*/ )
00051       { return 0; }
00052 
00053       void structuredErrorFunc( void * userData, xmlErrorPtr error )
00054       {
00055         if ( error )
00056           {
00057 #define X(m) SEC << " " << #m << "\t" << error->m << endl
00058 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
00059             X(domain);
00060             X(code);
00061             XS(message);
00062             X(level);
00063             XS(file);
00064             X(line);
00065             XS(str1);
00066             XS(str2);
00067             XS(str3);
00068             X(int1);
00069             X(int2);
00070             X(ctxt);
00071             X(node);
00072 #undef X
00073 #undef XS
00074           }
00075       }
00076 
00078     } // namespace
00080 
00082     //
00083     //  METHOD NAME : Reader::Reader
00084     //  METHOD TYPE : Constructor
00085     //
00086     Reader::Reader( const InputStream & stream_r,
00087                     const Validate & validate_r )
00088     : _stream( stream_r )
00089     , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
00090                                stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
00091     , _node( _reader )
00092     {
00093       if ( ! _reader || ! stream_r.stream().good() )
00094         ZYPP_THROW( Exception( "Bad input stream" ) );
00095       // set error handler
00096       xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
00097       // TODO: set validation
00098 
00099       // advance to 1st node
00100       nextNode();
00101     }
00102 
00104     //
00105     //  METHOD NAME : Reader::~Reader
00106     //  METHOD TYPE : Destructor
00107     //
00108     Reader::~Reader()
00109     {
00110       if ( _reader )
00111         {
00112           xmlFreeTextReader( _reader );
00113         }
00114     }
00115 
00116     XmlString Reader::nodeText()
00117     {
00118       if ( ! _node.isEmptyElement() )
00119       {
00120         if ( nextNode() )
00121         {
00122           if ( _node.nodeType() == XML_READER_TYPE_TEXT )
00123           {
00124             return _node.value();
00125           }
00126         }
00127       }
00128       return XmlString();
00129     }
00130     
00132     //
00133     //  METHOD NAME : Reader::nextNode
00134     //  METHOD TYPE : bool
00135     //
00136     bool Reader::nextNode()
00137     {
00138       int ret = xmlTextReaderRead( _reader );
00139       if ( ret == 1 )
00140         {
00141           return true;
00142         }
00143       xmlTextReaderClose( _reader );
00144       if ( ret != 0 )
00145         {
00146           ZYPP_THROW( Exception( "Parse error" ) );
00147         }
00148       return false;
00149     }
00150 
00152     //
00153     //  METHOD NAME : Reader::nextNodeAttribute
00154     //  METHOD TYPE : bool
00155     //
00156     bool Reader::nextNodeAttribute()
00157     {
00158       int ret = xmlTextReaderMoveToNextAttribute( _reader );
00159       if ( ret == 1 )
00160         {
00161           return true;
00162         }
00163       if ( ret != 0 )
00164         {
00165           ZYPP_THROW( Exception( "Parse error" ) );
00166         }
00167       return false;
00168     }
00169 
00171     //
00172     //  METHOD NAME : Reader::close
00173     //  METHOD TYPE : void
00174     //
00175     void Reader::close()
00176     {
00177       if ( _reader )
00178         {
00179           xmlTextReaderClose( _reader );
00180         }
00181     }
00182 
00184     //
00185     //  METHOD NAME : Reader::seekToNode
00186     //  METHOD TYPE : bool
00187     //
00188     bool Reader::seekToNode( int depth_r, const std::string & name_r )
00189     {
00190       do
00191         {
00192           if ( _node.depth() == depth_r
00193                && _node.name() == name_r
00194                && _node.nodeType() == XML_READER_TYPE_ELEMENT )
00195             {
00196               break;
00197             }
00198         } while( nextNode() );
00199 
00200       return ! atEnd();
00201     }
00202 
00204     //
00205     //  METHOD NAME : Reader::seekToEndNode
00206     //  METHOD TYPE : bool
00207     //
00208     bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
00209     {
00210       // Empty element has no separate end node: <node/>
00211       do
00212         {
00213           if ( _node.depth() == depth_r
00214                && _node.name() == name_r
00215                && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
00216                     || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
00217                          && _node.isEmptyElement() ) ) )
00218             {
00219               break;
00220             }
00221         } while( nextNode() );
00222 
00223       return ! atEnd();
00224     }
00225 
00227   } // namespace xml
00230 } // namespace zypp

Generated on Tue Sep 25 19:23:03 2007 for libzypp by  doxygen 1.5.3