00001
00002
00003
00004
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 * )
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 }
00080
00082
00083
00084
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
00096 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
00097
00098
00099
00100 nextNode();
00101 }
00102
00104
00105
00106
00107
00108 Reader::~Reader()
00109 {
00110 if ( _reader )
00111 {
00112 xmlFreeTextReader( _reader );
00113 }
00114 }
00115
00117
00118
00119
00120
00121 bool Reader::nextNode()
00122 {
00123 int ret = xmlTextReaderRead( _reader );
00124 if ( ret == 1 )
00125 {
00126 return true;
00127 }
00128 xmlTextReaderClose( _reader );
00129 if ( ret != 0 )
00130 {
00131 ZYPP_THROW( Exception( "Parse error" ) );
00132 }
00133 return false;
00134 }
00135
00137
00138
00139
00140
00141 bool Reader::nextNodeAttribute()
00142 {
00143 int ret = xmlTextReaderMoveToNextAttribute( _reader );
00144 if ( ret == 1 )
00145 {
00146 return true;
00147 }
00148 if ( ret != 0 )
00149 {
00150 ZYPP_THROW( Exception( "Parse error" ) );
00151 }
00152 return false;
00153 }
00154
00156
00157
00158
00159
00160 void Reader::close()
00161 {
00162 if ( _reader )
00163 {
00164 xmlTextReaderClose( _reader );
00165 }
00166 }
00167
00169
00170
00171
00172
00173 bool Reader::seekToNode( int depth_r, const std::string & name_r )
00174 {
00175 do
00176 {
00177 if ( _node.depth() == depth_r
00178 && _node.name() == name_r
00179 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
00180 {
00181 break;
00182 }
00183 } while( nextNode() );
00184
00185 return ! atEnd();
00186 }
00187
00189
00190
00191
00192
00193 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
00194 {
00195
00196 do
00197 {
00198 if ( _node.depth() == depth_r
00199 && _node.name() == name_r
00200 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
00201 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
00202 && _node.isEmptyElement() ) ) )
00203 {
00204 break;
00205 }
00206 } while( nextNode() );
00207
00208 return ! atEnd();
00209 }
00210
00212 }
00215 }