1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/parser/xml/Reader.cc
12 #include <libxml/xmlreader.h>
13 #include <libxml/xmlerror.h>
17 #include <zypp/base/LogControl.h>
18 #include <zypp/base/LogTools.h>
19 #include <zypp/base/Exception.h>
20 #include <zypp/base/String.h>
22 #include <zypp/parser/xml/Reader.h>
26 ///////////////////////////////////////////////////////////////////
28 { /////////////////////////////////////////////////////////////////
29 ///////////////////////////////////////////////////////////////////
31 { /////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
37 int ioread( void * context_r, char * buffer_r, int bufferLen_r )
39 if ( context_r && buffer_r )
41 return reinterpret_cast<InputStream *>(context_r)
42 ->stream().read( buffer_r, bufferLen_r ).gcount();
44 INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl;
48 int ioclose( void * /*context_r*/ )
52 std::list<std::string> structuredErrors;
53 void structuredErrorFunc( void * userData, xmlErrorPtr error )
57 // error->message is NL terminated
58 std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
59 str::stripSuffix( error->message, "\n" ).c_str() ) );
60 structuredErrors.push_back( err );
66 #define X(m) SEC << " " << #m << "\t" << error->m << endl
67 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
87 struct ParseException : public Exception
90 : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
92 for_( it, structuredErrors.begin(), --structuredErrors.end() )
97 /////////////////////////////////////////////////////////////////
99 ///////////////////////////////////////////////////////////////////
101 ///////////////////////////////////////////////////////////////////
103 // METHOD NAME : Reader::Reader
104 // METHOD TYPE : Constructor
106 Reader::Reader( const InputStream & stream_r,
107 const Validate & validate_r )
108 : _stream( stream_r )
109 , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
110 stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
113 MIL << "Start Parsing " << _stream << endl;
114 if ( ! _reader || ! stream_r.stream().good() )
115 ZYPP_THROW( Exception( "Bad input stream" ) );
117 // TODO: Fix using a global lastStructuredError string is not reentrant.
118 structuredErrors.clear();
119 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
120 // TODO: set validation
122 // advance to 1st node
126 ///////////////////////////////////////////////////////////////////
128 // METHOD NAME : Reader::~Reader
129 // METHOD TYPE : Destructor
135 xmlFreeTextReader( _reader );
137 MIL << "Done Parsing " << _stream << endl;
140 XmlString Reader::nodeText()
142 if ( ! _node.isEmptyElement() )
146 if ( _node.nodeType() == XML_READER_TYPE_TEXT )
148 return _node.value();
155 ///////////////////////////////////////////////////////////////////
157 // METHOD NAME : Reader::nextNode
158 // METHOD TYPE : bool
160 bool Reader::nextNode()
162 int ret = xmlTextReaderRead( _reader );
167 xmlTextReaderClose( _reader );
170 ZYPP_THROW( ParseException() );
175 ///////////////////////////////////////////////////////////////////
177 // METHOD NAME : Reader::nextNodeAttribute
178 // METHOD TYPE : bool
180 bool Reader::nextNodeAttribute()
182 int ret = xmlTextReaderMoveToNextAttribute( _reader );
189 ZYPP_THROW( ParseException() );
194 ///////////////////////////////////////////////////////////////////
196 // METHOD NAME : Reader::close
197 // METHOD TYPE : void
203 xmlTextReaderClose( _reader );
207 ///////////////////////////////////////////////////////////////////
209 // METHOD NAME : Reader::seekToNode
210 // METHOD TYPE : bool
212 bool Reader::seekToNode( int depth_r, const std::string & name_r )
216 if ( _node.depth() == depth_r
217 && _node.name() == name_r
218 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
222 } while( nextNode() );
227 ///////////////////////////////////////////////////////////////////
229 // METHOD NAME : Reader::seekToEndNode
230 // METHOD TYPE : bool
232 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
234 // Empty element has no separate end node: <node/>
237 if ( _node.depth() == depth_r
238 && _node.name() == name_r
239 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
240 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
241 && _node.isEmptyElement() ) ) )
245 } while( nextNode() );
250 /////////////////////////////////////////////////////////////////
252 ///////////////////////////////////////////////////////////////////
253 /////////////////////////////////////////////////////////////////
255 ///////////////////////////////////////////////////////////////////