posts - 262,  comments - 221,  trackbacks - 0
Informa不仅提供了对不同版本的RSS Feed source的读入和解析,同样也提供了将channel object导出为不同协议版本的XML文件的功能。这个功能是通过exporters包下的各个导出类来完成的。目前仅支持对RSS协议的导出,不支持Atom协议、OPML协议的导出。

所有的导出类都实现了ChannelExporterIF接口
/**
 * A channel exporter is used to write channel objects in an
 * implementation dependent way to an implicit destination.</p>
 *
 * 
@author Niko Schmuck (niko@nava.de) 
 
*/

public interface ChannelExporterIF {

  
/**
   * Writes the given channel to an implicit implementation dependent
   * destination.
   *
   * 
@param channel - The channel to be exported/written;
   *                  an object implementing ChannelIF.
   * 
@throws IOException - Thrown if writing the channel fails.
   
*/

  
void write(ChannelIF channel) throws IOException;

}

★RSS_0_91_Exporter

RSS_0_91_Exporter中提供了几种构造方法
public RSS_0_91_Exporter(String filename) throws IOException {
    
this(new File(filename), "utf-8");
}


public RSS_0_91_Exporter(File file) throws IOException {
    
this(file, "utf-8");
}


public RSS_0_91_Exporter(File file, String encoding) throws IOException {
    
this.writer = new OutputStreamWriter(new FileOutputStream(file),
    encoding);
    
this.encoding = encoding;
}


public RSS_0_91_Exporter(Writer writer, String encoding) {
    
this.writer = writer;
    
this.encoding = encoding;
}

真正的生成XML文件的过程其实很简单,就是按照RSS 0.9.1规范的格式将channel object的属性映射到XML文件的element去。
        // create items for channel
        Collection<ItemIF> items = channel.getItems();
        Iterator
<ItemIF> it = items.iterator();
        
while (it.hasNext()) {
            ItemIF item 
= (ItemIF) it.next();
            Element itemElem 
= new Element("item");
            itemElem.addContent(
new Element("title").
                    setText(item.getTitle()));
            
if (item.getLink() != null{
                itemElem.addContent(
new Element("link").
                        setText(item.getLink().toString()));
            }

            
if (item.getDescription() != null{
                itemElem.addContent(
new Element("description").
                        setText(item.getDescription()));
            }

            
if (item.getDate() != null{
                itemElem.addContent(
new Element("pubDate").
                        setText(ParserUtils.formatDate(item.getDate())));
            }

            channelElem.addContent(itemElem);
        }

这是write(Channel)方法的其中一个片段,是用于导出channel中的item节点的。

RSS_2_0_Exporter

和RSS 0.9.1的导出类似,2.0版本的导出同样需要实现ChannelExporterIF接口,同样提供了和上面一样参数类型的构造方法。不同的是在2.0的版本,由于新增了几个定义,所以增加了对应的构建方法。例如下面的getCategoryElements方法

    // ------------------------------------------------------------
    
// Build a hierarchical category String from CategoryIF
    
// ------------------------------------------------------------

    
private Element getCategoryElements(Element elem, CategoryIF category,
            StringBuffer catString) 
{
        StringBuffer l_catString;
        
if (catString == null || catString.length() < 1)
            l_catString = new StringBuffer(category.getTitle());

        
else
            l_catString = catString.append("/").append(category.getTitle());


        Collection
<CategoryIF> categories = category.getChildren();
        
if (categories.size() == 0{
            elem.addContent(
new Element("category").setText(l_catString
                    .toString()));
        }
 else {
            Iterator
<CategoryIF> catIt = categories.iterator();
            
while (catIt.hasNext()) {
                CategoryIF childCat 
= (CategoryIF) catIt.next();
                elem = getCategoryElements(elem, childCat, l_catString);

            }

        }

        
return elem;
    }

这个方法采用递归的方式,获取一个channel所属于的category,因为在Category对象中,关系是以级联的方式存在的,要把这种对象的级联关系展开为平行的字符串,只能通过递归的方式访问到最底层的category对象,得到其title后,再用分隔符"/"拼接后返回给上一层。

在2.0的write方法中,新增了对Namespace的支持
 Namespace dcNs = Namespace.getNamespace("dc", NS_DC);
 Namespace syNs 
= Namespace.getNamespace("sy", NS_SY);
 Namespace adminNs 
= Namespace.getNamespace("admin", NS_ADMIN);

其余的生成过程和0.9.1的基本相同,除了在category方面
        if (channel.getCategories() != null{
            Collection<CategoryIF> categories = channel.getCategories();

            Iterator
<CategoryIF> catIt = categories.iterator();
            
while (catIt.hasNext()) {
                CategoryIF cat 
= (CategoryIF) catIt.next();
                channelElem = getCategoryElements(channelElem, cat, null);

            }

        }

RSS_1_0_Exporter

RSS_1_0_Exporter导出和0.9.1和2.0协议的过程有些不同,区别在于item方面和部分属性,这里重点介绍一下item方面的导出过程
        // ===========================================
        Element itemsElem = new Element("items", defNs);
        Element seqElem 
= new Element("Seq", rdfNs);
        Collection
<ItemIF> items = channel.getItems();
        Iterator
<ItemIF> it = items.iterator();
        
while (it.hasNext()) {
            ItemIF item 
= (ItemIF) it.next();
            Element itemElem 
= new Element("li", rdfNs);
            
if (item.getLink() != null{
                itemElem.setAttribute(
"resource", item.getLink().toString());
            }

            seqElem.addContent(itemElem);
        }

        itemsElem.addContent(seqElem);
        channelElem.addContent(itemsElem);
        rootElem.addContent(channelElem);

        
// item-by-item en detail
        items = channel.getItems();
        it 
= items.iterator();
        
while (it.hasNext()) {
            ItemIF item 
= (ItemIF) it.next();
            Element itemElem 
= new Element("item", defNs);
            
if (item.getLink() != null{
                itemElem.setAttribute(
"about"
                    item.getLink().toString(), rdfNs);
            }

            itemElem.addContent(
new Element("title", defNs).
                    setText(item.getTitle()));
            
if (item.getLink() != null{
                itemElem.addContent(
new Element("link", defNs).
                    setText(item.getLink().toString()));
            }

            
if (item.getDescription() != null{
                itemElem.addContent(
new Element("description", dcNs).
                    setText(item.getDescription()));
            }

            
if (item.getDate() != null{
                itemElem.addContent(
new Element("date", dcNs).
                    setText(ParserUtils.formatDate(item.getDate())));
            }


            rootElem.addContent(itemElem);
        }

和0.9.1和2.0协议不同,1.0的RSS对于item的描述有2次,第一次是summary,第二次是detail。
<items>
      
<rdf:Seq>
        
<rdf:li resource="http://xml.com/pub/2000/08/09/xslt/xslt.html" />
        
<rdf:li resource="http://xml.com/pub/2000/08/09/rdfdb/index.html" />
      
</rdf:Seq>
    
</items>

<item rdf:about="http://xml.com/pub/2000/08/09/xslt/xslt.html">
    
<title>Processing Inclusions with XSLT</title>
    
<link>http://xml.com/pub/2000/08/09/xslt/xslt.html</link>
    
<description>
     Processing document inclusions with general XML tools can be 
     problematic. This article proposes a way of preserving inclusion 
     information through SAX-based processing.
    
</description>
  
</item>
  
  
<item rdf:about="http://xml.com/pub/2000/08/09/rdfdb/index.html">
    
<title>Putting RDF to Work</title>
    
<link>http://xml.com/pub/2000/08/09/rdfdb/index.html</link>
    
<description>
     Tool and API support for the Resource Description Framework 
     is slowly coming of age. Edd Dumbill takes a look at RDFDB, 
     one of the most exciting new RDF toolkits.
    
</description>
  
</item>

可以看到上面的<items>是大概地告知了RSS阅读器这个channel下面有多少个item,顺序如何。下面每一个<item>则是对上面提到的item的详细描述。根据规范,<item>节点的rdf:about属性值必须和rdf:li的resource属性值一样。

上面的代码就是先找出item的列表,构建<items>节点及其子节点<rdf:seq>,后面是构建<item>节点。所以有2次的节点迭代操作。


-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2010-01-04 10:15 Paul Lin 阅读(396) 评论(0)  编辑  收藏 所属分类: J2SE

只有注册用户登录后才能发表评论。


网站导航:
 
<2010年1月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜