001    /*
002     * Copyright 1999,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.feedparser;
018    
019    import java.util.Iterator;
020    import java.util.List;
021    
022    import org.jaxen.jdom.JDOMXPath;
023    import org.jdom.Element;
024    
025    /**
026     * Handles parsing OPML.
027     *
028     * @author <a href="mailto:burton@apache.org">Kevin A. Burton (burtonator)</a>
029     * @version $Id: OPMLFeedParser.java 373614 2006-01-30 22:31:21Z mvdb $
030     */
031    public class OPMLFeedParser {
032    
033        /**
034         * Parse this feed.
035         *
036         * 
037         */
038        public static void parse( FeedParserListener listener,
039                                  org.jdom.Document doc ) throws FeedParserException {
040    
041            try {
042                    
043                FeedParserState state = new FeedParserState();
044    
045                //will result in an incorrect interface if the caller isn't using the
046                //system correctly.
047    
048                FeedVersion v = new FeedVersion();
049                v.isOPML = true;
050                listener.onFeedVersion( v );
051    
052                listener.init();
053    
054                FeedDirectoryParserListener fdpl = (FeedDirectoryParserListener)listener;
055    
056                //this should be the root directory.
057                JDOMXPath xpath = new JDOMXPath( "/opml/body/outline" );
058                List list = xpath.selectNodes( doc );
059    
060                Iterator i = list.iterator();
061                while ( i.hasNext() ) {
062    
063                    Element child = (Element)i.next();
064                    onOutline( fdpl, state, child );
065                    
066                }
067                
068                listener.finished();
069    
070            } catch ( Throwable t ) { throw new FeedParserException( t ); }
071    
072        }
073    
074        private static void onOutlineFolder( FeedDirectoryParserListener listener,
075                                             FeedParserState state,
076                                             Element current ) throws Exception {
077    
078            JDOMXPath xpath = new JDOMXPath( "outline" );
079            List list = xpath.selectNodes( current );
080    
081            Iterator i = list.iterator();
082            while ( i.hasNext() ) {
083    
084                Element child = (Element)i.next();
085                onOutline( listener, state, child );
086                    
087            }
088    
089        }
090            
091        private static void onOutline( FeedDirectoryParserListener listener,
092                                       FeedParserState state,
093                                       Element current ) throws Exception {
094    
095            String title = current.getAttributeValue( "title" );
096    
097            if ( title == null )
098                title = current.getAttributeValue( "text" );
099    
100            String weblog = current.getAttributeValue( "htmlUrl" );
101            String description = current.getAttributeValue( "description" );
102            String feed = current.getAttributeValue( "xmlUrl" );
103    
104            if ( weblog == null )
105                weblog = feed;
106            
107            if ( feed != null ) {
108                listener.onItem( state, title, weblog, description, feed );
109            } else if ( title != null ) {
110                //this is almost certainly a folder
111                
112                listener.onFolder( state, title );
113                onOutlineFolder( listener, state, current );
114                listener.onFolderEnd();
115                        
116            }
117    
118        }
119    
120    }
121