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 #if LIBXML_VERSION >= 21200
54 void structuredErrorFunc( void * userData, const xmlError * error )
56 void structuredErrorFunc( void * userData, xmlError * error )
61 // error->message is NL terminated
62 std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line,
63 str::stripSuffix( error->message, "\n" ).c_str() ) );
64 structuredErrors.push_back( err );
70 #define X(m) SEC << " " << #m << "\t" << error->m << endl
71 #define XS(m) SEC << " " << #m << "\t" << (error->m?error->m:"NA") << endl
91 struct ParseException : public Exception
94 : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) )
96 for_( it, structuredErrors.begin(), --structuredErrors.end() )
101 /////////////////////////////////////////////////////////////////
103 ///////////////////////////////////////////////////////////////////
105 ///////////////////////////////////////////////////////////////////
107 // METHOD NAME : Reader::Reader
108 // METHOD TYPE : Constructor
110 Reader::Reader( const InputStream & stream_r,
111 const Validate & validate_r )
112 : _stream( stream_r )
113 , _reader( xmlReaderForIO( ioread, ioclose, &_stream,
114 stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) )
117 MIL << "Start Parsing " << _stream << endl;
118 if ( ! _reader || ! stream_r.stream().good() )
119 ZYPP_THROW( Exception( "Bad input stream" ) );
121 // TODO: Fix using a global lastStructuredError string is not reentrant.
122 structuredErrors.clear();
123 xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL );
124 // TODO: set validation
126 // advance to 1st node
130 ///////////////////////////////////////////////////////////////////
132 // METHOD NAME : Reader::~Reader
133 // METHOD TYPE : Destructor
139 xmlFreeTextReader( _reader );
141 MIL << "Done Parsing " << _stream << endl;
144 XmlString Reader::nodeText()
146 if ( ! _node.isEmptyElement() )
150 if ( _node.nodeType() == XML_READER_TYPE_TEXT )
152 return _node.value();
159 ///////////////////////////////////////////////////////////////////
161 // METHOD NAME : Reader::nextNode
162 // METHOD TYPE : bool
164 bool Reader::nextNode()
166 int ret = xmlTextReaderRead( _reader );
171 xmlTextReaderClose( _reader );
174 ZYPP_THROW( ParseException() );
179 ///////////////////////////////////////////////////////////////////
181 // METHOD NAME : Reader::nextNodeAttribute
182 // METHOD TYPE : bool
184 bool Reader::nextNodeAttribute()
186 int ret = xmlTextReaderMoveToNextAttribute( _reader );
193 ZYPP_THROW( ParseException() );
198 ///////////////////////////////////////////////////////////////////
200 // METHOD NAME : Reader::close
201 // METHOD TYPE : void
207 xmlTextReaderClose( _reader );
211 ///////////////////////////////////////////////////////////////////
213 // METHOD NAME : Reader::seekToNode
214 // METHOD TYPE : bool
216 bool Reader::seekToNode( int depth_r, const std::string & name_r )
220 if ( _node.depth() == depth_r
221 && _node.name() == name_r
222 && _node.nodeType() == XML_READER_TYPE_ELEMENT )
226 } while( nextNode() );
231 ///////////////////////////////////////////////////////////////////
233 // METHOD NAME : Reader::seekToEndNode
234 // METHOD TYPE : bool
236 bool Reader::seekToEndNode( int depth_r, const std::string & name_r )
238 // Empty element has no separate end node: <node/>
241 if ( _node.depth() == depth_r
242 && _node.name() == name_r
243 && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT
244 || ( _node.nodeType() == XML_READER_TYPE_ELEMENT
245 && _node.isEmptyElement() ) ) )
249 } while( nextNode() );
254 /////////////////////////////////////////////////////////////////
256 ///////////////////////////////////////////////////////////////////
257 /////////////////////////////////////////////////////////////////
259 ///////////////////////////////////////////////////////////////////