代码改变世界

Jumony(外一)HTML和数据,同时发布第一个CTP源代码。

2010-08-18 12:22  Ivony...  阅读(3749)  评论(17编辑  收藏  举报

Jumony(一)从扩展方法到流畅的程序体验

Jumony(二)jQuery的设计艺术和选择器

Jumony(三)第一个公开预览版,在.NET里玩转jQuery选择器!

 

首先是兑现诺言,上一篇文章中曾经说到源代码会随下一篇文章的发布一同发布。其实我早已打包好了,现在提供下载地址:

https://files.cnblogs.com/Ivony/Jumony_CTP(20100802)_Source.rar

有人说里面漏了HtmlAgilityPack和Ivony.Fluent的源代码。这是因为这两个项目不是Jumony的一部分。HtmlAgilityPack是一个老外的开源项目,而Ivony.Fluent则是一些通用的扩展方法来辅助流畅体验的。不过为了方便大家,也提供这两个项目对应的源代码下载:

Ivony.Fluent的:

https://files.cnblogs.com/Ivony/Ivony.Fluent(ver.62).rar

HtmlAgilityPack的:

https://files.cnblogs.com/Ivony/HtmlAgilityPack(ver.62).rar

ver.62是SVN的内部版本号。

 

建议大家下载HtmlAgility最新的版本,也许修正了很多Bug,除非HtmlAgilityAdapter与其不兼容。

http://htmlagilitypack.codeplex.com/

 

其实也有计划做MSHTML的Adapter,但文档翻得眼睛花,暂时作罢。

 

 

这个CTP中其实还存在很多的问题,其中已知的问题都已经被修复,将不会在下一个CTP版本中看到,这些包括但不限于:

  • .className选择器被错误的解释成[class*=className],正确的应该是[class~=className]
  • SiblingsAfterSelf会错误的包含自身
  • HtmlBindingContext的Commit方法行为诡异
  • 等等等等。

 

这是Jumony系列中一篇比较短的文章,与大家一起来探讨Jumony的一些好玩的应用。上一篇文章有很多人留言说下载了Jumony的CTP,但我不知道到底大家有没有真正去玩。这个框架我是一边写,一边玩,玩的过程中产生了大量的需求,然后一一实现。废话不多说,先来看一个截图:

1

 

嗯,很明显,这是老赵的博客,似乎没什么奇怪的。但是等等,老赵啥时候写过这些文章?!

没错,这些文章都是博客园首页的!

 

当然这是一件很简单的事情,从博客园的首页摘取文章内容,再把它填到老赵的博客里面去。说起来似乎很容易,但真正做起来恐怕不是那么简单的事情吧。

 

那么我们来看看Jumony能够怎样帮助我们解决这种问题?

  public void ProcessRequest( HttpContext context )
  {

    var client = new WebClient();

    client.Encoding = System.Text.Encoding.UTF8;

    var parser = new JumonyParser();

    var cnblogs = parser.Parse( client.DownloadString( "http://www.cnblogs.com/" ) );
    var zhaojie = parser.Parse( client.DownloadString( "http://blog.zhaojie.me/" ) );

    var baseElement = cnblogs.GetNodeFactory().CreateElement( "base" );
    baseElement.SetAttribute( "href" ).Value( "http://blog.zhaojie.me/" );

    zhaojie.FindSingle( "head" ).InsertCopy( 0, baseElement );


    zhaojie.Find( ".post" ).BindFrom( cnblogs.Find( ".post_item" ), ( cb, zj ) =>
      {
        zj.FindSingle( "h2 a" ).SetAttribute( "href" ).Value( cb.FindSingle( "h3 a" ).Attribute( "href" ).Value() );
        zj.FindSingle( "h2 a" ).InnerText( cb.FindSingle( "h3 a" ).InnerText() );

        zj.FindSingle( ".entry strong" ).NextNode().ReplaceCopy( cb.FindSingle( ".post_item_summary" ).Nodes().Last() );


        zj.FindSingle( ".icon_comment a" ).SetAttribute( "href" ).Value( cb.FindSingle( ".article_comment a" ).Attribute( "href" ).Value() );
        zj.FindSingle( ".icon_comment a" ).InnerText( cb.FindSingle( ".article_comment a span" ).InnerText() + " Comments" );

      } );


    context.Response.Write( zhaojie );

  }

 

真正干活的其实就五行代码,分别是,把文章的标题、标题连接、文章摘要、回复数量、回复量的链接复制过去。

  

注意,这段代码用现在发布的这个CTP版本是无法通过编译的,因为现在的这个CTP版本尚不支持InnerText这样的对文档进行修改的方法。

 

 

从这个例子我们也能看到C# 3.0的一些不足,如果我们用函数式的语言来写这段代码,就没有这么多乱七八糟的括号,语义也将更加流畅。

 

而如果用动态语言,我们甚至可以写成:

zj.FindSingle( "h2 a" ).href = cb.FindSingle( "h3 a" ).href;
zj.FindSingle( "h2 a" ).text = cb.FindSingle( "h3 a" ).text;

zj.FindSingle( ".entry strong" ).next = cb.FindSingle( ".post_item_summary" ).nodes.last;


zj.FindSingle( ".icon_comment a" ).href = cb.FindSingle( ".article_comment a" ).href;
zj.FindSingle( ".icon_comment a" ).text = cb.FindSingle( ".article_comment a span" ).text + " Comments";

 

这并不是痴人说梦,而是Jumony正在努力的方向。

 

借助CSS选择器,Jumony可以轻易地将HTML文档的表现形式和包含数据完全分离。

在这个例子里,我们可以看到这种流畅的感受,加载博客园的首页,将数据抽出,再加载老赵的博客,将数据填入。一气呵成,比XSLT的语法更为简洁。

当然,我们之所以可以轻易地做到这一点,也与语义网的普及密不可分,由于HTML越来越语义化,我们从中抽取数据的过程便越来越简单。但这并不代表对于脏乱的HTML我们就没有办法抽取,事实上只是麻烦一点而已。

 

 

其实,我们有什么必要去做模板呢?

如果你要高兴我的博客长得和老赵的一个样,用Jumony几行代码就搞定了。

 

 

 

Technorati 标签: Jumony