Reader.cc
Go to the documentation of this file.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 #include "zypp/base/String.h"
00024
00025 #include "zypp/parser/xml/Reader.h"
00026
00027 using std::endl;
00028
00030 namespace zypp
00031 {
00032
00033 namespace xml
00034 {
00035
00037 namespace
00038 {
00039
00040 int ioread( void * context_r, char * buffer_r, int bufferLen_r )
00041 {
00042 if ( context_r && buffer_r )
00043 {
00044 return reinterpret_cast<InputStream *>(context_r)
00045 ->stream().read( buffer_r, bufferLen_r ).gcount();
00046 }
00047 INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl;
00048 return -1;
00049 }
00050
00051 int ioclose( void * )
00052 { return 0; }
00053
00054
00055 std::list<std::string> structuredErrors;
00056 void structuredErrorFunc( void * userData, xmlErrorPtr error )
00057 {
00058 if ( error )
00059 {
00060
00061 std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
00062 str::stripSuffix( error->message, "\n" ).c_str() ) );
00063 structuredErrors.push_back( err );
00064 WAR << err << endl;
00065 }
00066 #if 0
00067 if ( error )
00068 {
00069 #define X(m) SEC << " " << #m << "\t" << error->m << endl
00070 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
00071 X(domain);
00072 X(code);
00073 XS(message);
00074 X(level);
00075 XS(file);
00076 X(line);
00077 XS(str1);
00078 XS(str2);
00079 XS(str3);
00080 X(int1);
00081 X(int2);
00082 X(ctxt);
00083 X(node);
00084 #undef X
00085 #undef XS
00086 }
00087 #endif
00088 }
00089
00090 struct ParseException : public Exception
00091 {
00092 ParseException()
00093 : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
00094 {
00095 for_( it, structuredErrors.begin(), --structuredErrors.end() )
00096 addHistory( *it );
00097 }
00098 };
00099
00101 }
00103
00105
00106
00107
00108
00109 Reader::Reader( const InputStream & stream_r,
00110 const Validate & validate_r )
00111 : _stream( stream_r )
00112 , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
00113 stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
00114 , _node( _reader )
00115 {
00116 MIL << "Start Parsing " << _stream << endl;
00117 if ( ! _reader || ! stream_r.stream().good() )
00118 ZYPP_THROW( Exception( "Bad input stream" ) );
00119
00120
00121 structuredErrors.clear();
00122 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
00123
00124
00125
00126 nextNode();
00127 }
00128
00130
00131
00132
00133
00134 Reader::~Reader()
00135 {
00136 if ( _reader )
00137 {
00138 xmlFreeTextReader( _reader );
00139 }
00140 MIL << "Done Parsing " << _stream << endl;
00141 }
00142
00143 XmlString Reader::nodeText()
00144 {
00145 if ( ! _node.isEmptyElement() )
00146 {
00147 if ( nextNode() )
00148 {
00149 if ( _node.nodeType() == XML_READER_TYPE_TEXT )
00150 {
00151 return _node.value();
00152 }
00153 }
00154 }
00155 return XmlString();
00156 }
00157
00159
00160
00161
00162
00163 bool Reader::nextNode()
00164 {
00165 int ret = xmlTextReaderRead( _reader );
00166 if ( ret == 1 )
00167 {
00168 return true;
00169 }
00170 xmlTextReaderClose( _reader );
00171 if ( ret != 0 )
00172 {
00173 ZYPP_THROW( ParseException() );
00174 }
00175 return false;
00176 }
00177
00179
00180
00181
00182
00183 bool Reader::nextNodeAttribute()
00184 {
00185 int ret = xmlTextReaderMoveToNextAttribute( _reader );
00186 if ( ret == 1 )
00187 {
00188 return true;
00189 }
00190 if ( ret != 0 )
00191 {
00192 ZYPP_THROW( ParseException() );
00193 }
00194 return false;
00195 }
00196
00198
00199
00200
00201
00202 void Reader::close()
00203 {
00204 if ( _reader )
00205 {
00206 xmlTextReaderClose( _reader );
00207 }
00208 }
00209
00211
00212
00213
00214
00215 bool Reader::seekToNode( int depth_r, const std::string & name_r )
00216 {
00217 do
00218 {
00219 if ( _node.depth() == depth_r
00220 && _node.name() == name_r
00221 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
00222 {
00223 break;
00224 }
00225 } while( nextNode() );
00226
00227 return ! atEnd();
00228 }
00229
00231
00232
00233
00234
00235 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
00236 {
00237
00238 do
00239 {
00240 if ( _node.depth() == depth_r
00241 && _node.name() == name_r
00242 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
00243 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
00244 && _node.isEmptyElement() ) ) )
00245 {
00246 break;
00247 }
00248 } while( nextNode() );
00249
00250 return ! atEnd();
00251 }
00252
00254 }
00257 }