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
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
00134
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
00154
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
00173
00174
00175 void Reader::close()
00176 {
00177 if ( _reader )
00178 {
00179 xmlTextReaderClose( _reader );
00180 }
00181 }
00182
00184
00185
00186
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
00206
00207
00208 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
00209 {
00210
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 }
00230 }